Compare commits

..

2602 Commits

Author SHA1 Message Date
Windel Bouwman
cc24b73031 Set all versions to 0.1.0 2019-07-07 13:04:12 +02:00
Windel Bouwman
93f70abdf1 Merge pull request #1108 from RustPython/update-docs
Update documentation folder and readme.
2019-07-06 19:09:59 +02:00
Windel Bouwman
bcf470ee52 Merge pull request #1111 from RustPython/sys-version
Add git information in sys and platform modules.
2019-07-06 18:37:42 +02:00
Windel Bouwman
5c39350451 Revert Pipfile back to py36 2019-07-06 18:36:18 +02:00
Windel Bouwman
22c3ed3e1f Merge branch 'master' of github.com:RustPython/RustPython into update-docs 2019-07-06 17:01:33 +02:00
Windel Bouwman
ef649be941 Add git information in sys and platform modules. 2019-07-06 17:00:03 +02:00
Windel Bouwman
69980c23b7 Merge pull request #1109 from RustPython/update-travis-yml
Trial to improve travis config.
2019-07-06 16:02:07 +02:00
coolreader18
f041a0a50f Merge pull request #1110 from palaviv/wasm-warns
Remove wasm warnings
2019-07-06 08:38:59 -05:00
Aviv Palivoda
10cad47b50 Remove wasm warnings 2019-07-06 16:14:29 +03:00
Windel Bouwman
f68b064224 Stick to python3.6 for now. 2019-07-06 13:13:35 +02:00
Windel Bouwman
70c20543f8 Merge pull request #1106 from palaviv/syntex-error
Pass more information in user defined parse error
2019-07-06 13:02:11 +02:00
Windel Bouwman
ef44e7295e Trial to improve travis config. 2019-07-06 12:32:53 +02:00
Aviv Palivoda
0be08fe9f4 Fix wasm syntax error 2019-07-06 13:30:06 +03:00
Windel Bouwman
c64a974bfd Update documentation folder and readme. 2019-07-06 11:42:19 +02:00
Windel Bouwman
a099ba5f8e Merge pull request #1104 from palaviv/remove-importlib-frames
Remove importlib frames from traceback
2019-07-06 10:58:20 +02:00
Aviv Palivoda
0e74d16498 Pass ParseError location to CompileError 2019-07-06 10:23:32 +03:00
Aviv Palivoda
251e33af22 Add TODO on verbose 2019-07-06 09:16:23 +03:00
Aviv Palivoda
c70748fbaa Use filter 2019-07-06 09:15:21 +03:00
Aviv Palivoda
6239fe0fbc Remove importlib frames from traceback 2019-07-06 09:15:21 +03:00
Aviv Palivoda
ef1d5433df Pass more information in user defined parse error 2019-07-05 11:01:49 +03:00
coolreader18
22c0b085ad Merge pull request #1105 from palaviv/skip-modules
Allow skipping of unknown modules in whats_left.sh
2019-07-04 16:35:27 -05:00
Aviv Palivoda
2edba36de7 Allow skipping of unknown modules 2019-07-04 23:58:01 +03:00
coolreader18
f8e8a12ed2 Merge pull request #1102 from palaviv/clean-import
Remove old import
2019-07-04 13:16:50 -05:00
Aviv Palivoda
f740845bab Use vm.class 2019-07-04 17:38:55 +03:00
Aviv Palivoda
bb30d0fce0 Don't install external imports if there is no compiler 2019-07-04 17:36:27 +03:00
Aviv Palivoda
42d17138eb Remove old import 2019-07-04 17:32:17 +03:00
Aviv Palivoda
ee4ee5456f Use vm.import when running with -m 2019-07-04 17:32:17 +03:00
coolreader18
72febb77d0 Merge pull request #1103 from mkurnikov/importerror-attributes
Add name, path, msg attributes to ImportError
2019-07-03 18:17:03 -05:00
Maxim Kurnikov
9ce5240598 add name, path, msg attributes to ImportError 2019-07-03 22:18:49 +03:00
Windel Bouwman
df53d55c82 Merge pull request #1101 from palaviv/wasm-importlib
Use importlib import in WASM
2019-07-03 20:18:59 +02:00
coolreader18
f34f16b2cc Merge pull request #1095 from RustPython/coolreader18/whats_left-modules
Add module listing to whats_left.sh
2019-07-03 12:58:09 -05:00
Aviv Palivoda
090cfed593 Use importlib import in WASM 2019-07-03 18:57:49 +03:00
coolreader18
6b018a0b8b Merge pull request #1096 from RustPython/underscore2hyphen
Underscore2hyphen
2019-07-03 10:16:03 -05:00
coolreader18
96f6646063 Merge pull request #1098 from mkurnikov/pass-if-expression-to-function
Do not pollute stack when if-expression condition evaluated to False
2019-07-03 09:55:39 -05:00
Maxim Kurnikov
8162b87a00 Do not pollute stack when if-expression condition evaluated to False 2019-07-03 16:13:16 +03:00
coolreader18
3668250c12 Show module attributes missing 2019-07-01 14:21:29 -05:00
Windel Bouwman
6a58b76ef7 Change authors to team name. 2019-07-01 21:14:07 +02:00
Windel Bouwman
bedbad284e Change underscore into hyphen 2019-07-01 21:05:29 +02:00
Windel Bouwman
4a108c1ef5 Merge pull request #1059 from RustPython/unicodedata
Add initial unicodedata module.
2019-07-01 20:44:14 +02:00
Windel Bouwman
e05a75c363 Merge pull request #1092 from RustPython/bytecode-crate
Make parser and compiler optional features for vm crate.
2019-07-01 20:43:06 +02:00
coolreader18
92625857ba Allow specifying sections for whats_left.sh 2019-07-01 13:28:55 -05:00
coolreader18
f8cf39ebbb Change sys.path in not_impl_gen.py 2019-07-01 13:20:04 -05:00
coolreader18
982b2f2c14 Add comment to not_impl_gen.py 2019-07-01 13:11:43 -05:00
coolreader18
307990d5de Add module listing to whats_left.sh 2019-07-01 13:06:45 -05:00
coolreader18
dfabd4a2a1 Merge pull request #1093 from RustPython/getrow
Change get_row() into row()
2019-07-01 09:22:35 -05:00
coolreader18
fbd0c599a9 Merge pull request #1074 from JimJeon/feature/rmod
Implement int.__rmod__
2019-06-30 20:33:15 -05:00
JimJeon
2f1d4a8d29 Fix with rustfmt 2019-07-01 09:44:47 +09:00
Windel Bouwman
13be2cf3f4 Merge master branch 2019-06-30 21:22:33 +02:00
Windel Bouwman
5b534ade4d Merge pull request #1091 from palaviv/fix-import
Fix locals and globals in call to __import__
2019-06-30 20:43:52 +02:00
Windel Bouwman
f816a50110 Change get_row() into row() 2019-06-30 20:23:01 +02:00
Windel Bouwman
3954dbe716 Make parser and compiler optional features for vm crate. 2019-06-30 20:11:40 +02:00
Windel Bouwman
36adf45b27 Merge pull request #1086 from RustPython/bytecode-crate
Move bytecode into own crate.
2019-06-30 20:03:54 +02:00
coolreader18
602e4b7edb Merge pull request #1085 from RustPython/travis-configs
Simplify travis config.
2019-06-30 12:14:17 -05:00
Aviv Palivoda
49f3bf7401 Fix locals and globals in call to __import__ 2019-06-30 20:09:26 +03:00
coolreader18
6ba3553fcf Merge pull request #1089 from silmeth/serialization
improve (de)serialization: no crash on BigInts, non-string map keys
2019-06-30 10:10:31 -05:00
silmeth
5dddd02bca improve (de)serialization: no crash on BigInts, non-string map keys 2019-06-30 16:10:58 +02:00
Windel Bouwman
f1d250b10a Merge branch 'master' of https://github.com/RustPython/RustPython into bytecode-crate 2019-06-30 11:42:47 +02:00
Windel Bouwman
e40c844be7 Make bytecode crate independent of parser crate. 2019-06-30 11:42:36 +02:00
Windel Bouwman
183415e64b Move bytecode into own crate. 2019-06-30 11:01:40 +02:00
Windel Bouwman
a332b74ad8 Merge pull request #1064 from RustPython/cryptomods
Add initial hashlib module.
2019-06-30 10:58:49 +02:00
Windel Bouwman
7ab5d53642 update to newer version of DynDigest trait which allows clone. 2019-06-30 10:10:17 +02:00
Windel Bouwman
f0492eefb2 Merge pull request #1084 from silmeth/int-float-comparison
fix float–int cross-type comparisons
2019-06-30 09:25:49 +02:00
Windel Bouwman
598a0a9b79 Simplify travis config further. 2019-06-30 09:13:47 +02:00
Windel Bouwman
f0715fe388 Simplify travis config. 2019-06-30 09:04:57 +02:00
Windel Bouwman
ae684e323e Merge pull request #1065 from RustPython/coolreader18/wasm-test-traceback
Give more information in the error messages for failed wasm tests
2019-06-30 08:57:25 +02:00
coolreader18
4d5b4f5dbe Use new_import_error, fix serve command 2019-06-30 00:52:03 -04:00
Aviv Palivoda
4bf317c3af Merge pull request #1076 from corona10/complex_repr
Fix complex representation for negative imaginary number case.
2019-06-29 21:03:16 +03:00
Aviv Palivoda
546c1c0504 Merge pull request #1083 from palaviv/parse-level
Calculate import level at parsing
2019-06-29 20:49:22 +03:00
Aviv Palivoda
ed737026c3 Merge pull request #1082 from RustPython/xdrlib
Add xdrlib.py
2019-06-29 20:46:42 +03:00
Windel Bouwman
c7004f7b0f Merge pull request #1070 from corona10/ellipsis
Add "Ellipsis" for Ellipsis
2019-06-29 16:58:13 +02:00
silmeth
d0de3be2a9 fix float–int cross-type comparisons
Fixes #1069
2019-06-29 16:50:09 +02:00
Windel Bouwman
e88f7536b3 Improve single arm match. 2019-06-29 16:48:03 +02:00
Windel Bouwman
df31abea98 Merge branch 'master' of https://github.com/RustPython/RustPython into cryptomods 2019-06-29 16:46:00 +02:00
Dong-hee Na
8c318dcd3c Add "Ellipsis" for Ellipsis
Currently, only "..." works for Ellipsis type.
This PR will fix this code to work.
```python
a = Ellipsis
b = ...
a is b
```
2019-06-29 23:34:27 +09:00
Windel Bouwman
d185f53195 Merge pull request #1079 from sanxiyn/os-lstat
Implement os.lstat
2019-06-29 16:19:04 +02:00
Windel Bouwman
c0600860c8 Merge pull request #1081 from RustPython/travis-config
Disable code coverage on all branches except the master branch.
2019-06-29 16:16:16 +02:00
Aviv Palivoda
0d8d2e3beb Calculate import level at parsing 2019-06-29 17:04:31 +03:00
Windel Bouwman
ddc24d67dc Add xdrlib.py 2019-06-29 14:44:39 +02:00
Windel Bouwman
0a242b69a5 Merge pull request #1067 from palaviv/memoryview-slice
Memoryview slice
2019-06-29 14:41:46 +02:00
Windel Bouwman
5f3e5e1602 Disable code coverage on all branches except the master branch. 2019-06-29 14:18:54 +02:00
Windel Bouwman
f4d63c923a Switch to better supported crypto lib. 2019-06-29 14:03:19 +02:00
Windel Bouwman
09823a0a64 Merge pull request #1078 from corona10/sys.byteorder
sys.byteorder: Implement sys.byteorder
2019-06-29 13:24:41 +02:00
Windel Bouwman
18a49d10b5 Merge pull request #1077 from hannut91/add-tuple-rmul
Add tuple.__rmul__
2019-06-29 13:19:13 +02:00
JimJeon
5172a098bf Changed function name to rmod 2019-06-29 17:38:01 +09:00
Seo Sanghyeon
87d866d414 Implement os.lstat 2019-06-29 17:21:11 +09:00
Dong-hee Na
b1aa10d03e Fix complex representation for negative imaginary number case. 2019-06-29 16:30:34 +09:00
Dong-hee Na
103559101e sys.byteorder: Implement sys.byteorder 2019-06-29 16:16:03 +09:00
Aviv Palivoda
32be3bc110 Merge pull request #1071 from hannut91/add-resolve-path
Fix TestWithTempDir test to pass on Mac
2019-06-29 10:15:23 +03:00
Windel Bouwman
57de0ebc05 Merge pull request #1061 from RustPython/xdrlib
Add endianness support to struct module.
2019-06-29 09:05:54 +02:00
hannut91
91d901abdb Add tuple.__rmul__
Add tuple.__rmul__ and uncomment test snippet of __rmul__.
2019-06-29 16:02:42 +09:00
JimJeon
1e568f1044 Implement int.__rmod__
Extracted inner_mod function and used in int.__mod__ and int.__rmod__
and also added test snippets of int.__mod__ and int.__rmod__.
2019-06-29 15:21:28 +09:00
hannut91
1dc5daa4d8 Fix TestWithTempDir test to pass on Mac
Fix TestWithTmpeDir test that comapre os.getcwd() and tmpdir.
os.getcwd() returns the result of resolving the symbolic link. But tmpdir
absolute path. Testing fails on Mac because the /tmp directory is a symbolic
link. Comparing the results of resolving tempdir will pass the test. But
RustPython does not implement lstat, so it does not pass, but in CPython The
test passes.
2019-06-29 14:58:44 +09:00
coolreader18
212522a4bb Merge pull request #1068 from palaviv/imp-_fix_co_filename
Add empty _imp._fix_co_filename
2019-06-28 05:26:24 -05:00
Aviv Palivoda
a3dc98d172 Add empty _imp._fix_co_filename 2019-06-28 10:46:55 +03:00
Aviv Palivoda
5a8613c78a Add tests for memoryview 2019-06-28 10:28:48 +03:00
Aviv Palivoda
7d2c4b6b6e memoryview support __getitem__ 2019-06-28 10:19:44 +03:00
Aviv Palivoda
3c54494132 Merge pull request #1054 from mkurnikov/keyerror-cpython
KeyError should have passed key object as a first element of .args
2019-06-28 09:23:51 +03:00
Aviv Palivoda
da39dde31f Merge pull request #1062 from palaviv/file-io-fd
Improve FileIO
2019-06-28 09:18:54 +03:00
coolreader18
d44350d042 Make vm.import more clear 2019-06-27 13:56:34 -05:00
coolreader18
4959361d29 Give more information in the error messages for failed wasm tests 2019-06-27 13:56:03 -05:00
Windel Bouwman
0a369d821d Add initial hashlib module. 2019-06-27 19:09:35 +02:00
Maxim Kurnikov
848714e18e save passed object into the first .args parameter for dict/mappingproxy KeyError 2019-06-26 23:40:24 +03:00
Windel Bouwman
0642412027 Merge pull request #1057 from RustPython/coolreader18/cpython-libs2
Add CPython library modules needed for unittest
2019-06-26 21:56:34 +02:00
coolreader18
c78c95f03a Add CPython library modules needed for unittest 2019-06-26 11:39:10 -05:00
coolreader18
1f9fa724e0 Merge pull request #1063 from palaviv/eof-error
Add EOFError
2019-06-26 10:42:42 -05:00
Aviv Palivoda
f2dff1cd20 Add EOFError 2019-06-26 18:25:47 +03:00
Aviv Palivoda
8cdf19c5f9 FileIO.write support ByteArray 2019-06-26 18:17:47 +03:00
Windel Bouwman
9e194b3904 Add endianness support to struct module. 2019-06-26 16:38:11 +02:00
Windel Bouwman
4db83aca7f Add initial unicodedata module. 2019-06-26 13:41:58 +02:00
coolreader18
c96680a70c Merge pull request #1050 from palaviv/relative-import
Support relative import
2019-06-25 15:50:26 -05:00
coolreader18
6d5f381d70 Merge pull request #1056 from mkurnikov/args-in-exceptions
Add args attribute to exceptions, make __str__ and __repr__ compatible with CPython
2019-06-25 11:32:07 -05:00
Aviv Palivoda
dc7eb24aab Support fileno as name in FileIO 2019-06-25 19:13:27 +03:00
Aviv Palivoda
725cfcc58d compute_c_flag ignore chars after first 2019-06-25 18:48:30 +03:00
Aviv Palivoda
da4c0bccfa pass local variables to __import__ only if there is a frame 2019-06-25 18:15:28 +03:00
Maxim Kurnikov
8852abc6c3 make exception __repr__ compatible with python3.6 2019-06-24 22:19:59 +03:00
Maxim Kurnikov
1e53e6c168 specify python 3.6 specifically as a Pipfile venv target 2019-06-24 22:19:01 +03:00
Maxim Kurnikov
060cd75783 simplify exception_repr a bit 2019-06-24 18:13:18 +03:00
Maxim Kurnikov
82101d9f1a rename exc_repr -> exc_name to better describe what it refers to 2019-06-24 18:10:27 +03:00
Maxim Kurnikov
ff1049a1eb fix regression in the exception representation in the traceback 2019-06-24 18:09:27 +03:00
Maxim Kurnikov
cd1d7b1a43 add args attribute to exceptions, make __str__ and __repr__ compatible with CPython 2019-06-24 17:30:20 +03:00
coolreader18
3085eadcb5 Merge pull request #1055 from romab1998/feature/ord_bytes_bytearray
add bytearray and bytes input types for ord()
2019-06-23 21:16:54 -05:00
Windel Bouwman
ba88716fbe Merge pull request #1049 from RustPython/coolreader18/fromargs-span-errors
Improve errors messages for derive(FromArgs)
2019-06-23 20:59:11 +02:00
romab
7effca3533 added tests for ord() in tests/snippets 2019-06-23 23:25:12 +05:00
Aviv Palivoda
bb9d697a85 Merge pull request #1053 from RustPython/zen
Added the python zen module.
2019-06-23 18:27:31 +03:00
Aviv Palivoda
e8c0644a04 Test relative import from upper level 2019-06-23 18:21:02 +03:00
Aviv Palivoda
ae5259670c Test relative import 2019-06-23 18:21:02 +03:00
Aviv Palivoda
a5276df980 Support relative import 2019-06-23 18:21:02 +03:00
Windel Bouwman
eeb7551692 Merge pull request #1039 from RustPython/coolreader18/wasm-_js-module
[WASM] Add a JsValue class
2019-06-23 11:39:01 +02:00
Windel Bouwman
fee9c99950 Merge pull request #1026 from rmliddle/BytesIO
String/BytesIO
2019-06-23 11:37:11 +02:00
romab
f2922e3f25 add bytearray and bytes input types for ord() 2019-06-23 11:34:12 +05:00
rmliddle
9bc392ca70 removed duplicate c_flag function 2019-06-23 11:59:21 +10:00
rmliddle
026958a322 Resolved merge conflict 2019-06-23 11:39:46 +10:00
rmliddle
0f0a9369b5 Updated StringIO to use "StringIO" 2019-06-23 11:36:59 +10:00
Windel Bouwman
ed63ebd0a3 Added the python zen module. 2019-06-22 13:13:34 +02:00
Windel Bouwman
2f75562f14 Merge pull request #1045 from RustPython/coolreader18/pyclassmethod-attr
Add #[pyclassmethod] to #[pyimpl]
2019-06-22 12:40:49 +02:00
coolreader18
658b6ca9b9 Fix errors 2019-06-21 20:20:21 -05:00
coolreader18
298b05d56d Don't convert errors from js to python 2019-06-21 20:20:21 -05:00
coolreader18
8cf38f5b25 Move classmethods on JsValue to be normal methods 2019-06-21 20:20:21 -05:00
coolreader18
072c8725fc Fix get_prop on primitives 2019-06-21 20:20:21 -05:00
coolreader18
886f77bdff Add PyJsValue::instanceof 2019-06-21 20:20:20 -05:00
coolreader18
a3735da489 Move confirm and prompt to browser.py 2019-06-21 20:20:20 -05:00
coolreader18
5627ab2345 Add PyJsValue::construct() 2019-06-21 20:20:20 -05:00
coolreader18
93cdd94ab7 Add browser.py module 2019-06-21 20:20:20 -05:00
coolreader18
56bcb02a5e Add _js module and fix imports 2019-06-21 20:20:20 -05:00
coolreader18
61b26878de Add rustpython_vm::__exports module and fix warning 2019-06-21 20:20:19 -05:00
coolreader18
9bb5dcc663 Merge pull request #1051 from michelhe/get-rid-of-debug-print
Remove a mistakenly commited debug print
2019-06-21 13:58:04 -05:00
coolreader18
650139b918 Merge pull request #1048 from RustPython/revert-1037-coolreader18/option-source_path
Revert "Make CodeObject.source_path an Option<String>", just add a parameter to import_codeobj
2019-06-21 11:49:03 -05:00
Michel Heily
c972e7c73e Remove a mistakenly commited debug print 2019-06-21 12:57:58 +03:00
coolreader18
ba8b733139 Merge pull request #1044 from RustPython/coolreader18/ser_de-own-module
Move PyObject de/serialization to its own module
2019-06-20 23:44:13 -05:00
rmliddle
e96a7014c4 Updates BytesIO to use "BufferedIO" 2019-06-21 13:51:51 +10:00
coolreader18
c359c430c2 Add set_file_attr to import_codeobj 2019-06-20 22:43:13 -05:00
coolreader18
aefbae40e4 Revert "Make CodeObject.source_path an Option<String>" 2019-06-20 12:01:20 -05:00
coolreader18
cb832e9aa1 Improve errors messages for derive(FromArgs) 2019-06-20 11:57:59 -05:00
coolreader18
86b8c07581 Update Cargo.lock 2019-06-19 20:03:31 -05:00
coolreader18
0ac42ac9aa Add convenience functions 2019-06-19 17:30:09 -05:00
Windel Bouwman
30979d9f27 Merge pull request #1043 from yanganto/feat/unicode-iterals
support unicode literal
2019-06-19 19:13:13 +02:00
Antonio Yang
974dc683e4 support unicode literal
- support unicode literal \x with 2 digits
- support unicode literal \u with 4 digits
- support unicode literal \U with 8 digits
- avoid to parse \x as unicode literal in bytes
2019-06-20 00:30:38 +08:00
coolreader18
e68b4943ca Add #[pyclassmethod] to #[pyimpl] 2019-06-18 20:37:08 -05:00
coolreader18
7554dfa72e Merge pull request #1042 from palaviv/os-replace
Add os.rename and OSError.errno
2019-06-18 18:56:35 -05:00
coolreader18
9ac854aea5 Use serde_wasm_bindgen for wasm ser/de 2019-06-18 14:32:34 -05:00
coolreader18
a8d80193c7 Move PyObject serialization to its own file 2019-06-18 13:31:58 -05:00
Aviv Palivoda
17cd22b8e8 Test OSError errno 2019-06-18 19:06:41 +03:00
Aviv Palivoda
9ee1ad93e0 Test os.rename 2019-06-18 19:06:41 +03:00
Aviv Palivoda
2f408f2210 Add conversion from io::Error to OSError 2019-06-18 19:06:00 +03:00
Aviv Palivoda
700d7d4b62 Add os.rename 2019-06-18 19:02:04 +03:00
Windel Bouwman
0f73c746db Merge pull request #1032 from michelhe/printf-like-string-formatting
Printf-style formatting
2019-06-17 21:49:33 +02:00
Michel Heily
64af5c43df Add some test snippets for modulo string formatting 2019-06-17 19:35:09 +03:00
Michel Heily
adccfa63cf Fix bugs when parsing format specifiers with key mappings.
* Algorithm used for parsing the key from "%(key)d" format did not
handle multiple parenthesis correctly.

* Second problem is that they way we calculated number of consumed chars
was based on str::find, making the code vulnerable to false-positives.
2019-06-17 19:35:09 +03:00
Michel Heily
6fe2c43bf7 Move lambda to its own function in do_cformat 2019-06-17 19:35:09 +03:00
Michel Heily
fca4178353 Avoid unnecessary allocation in modulo formatting 2019-06-17 19:35:09 +03:00
Michel Heily
5d38b9b624 Simplify error handling for CFormatString::from_str 2019-06-17 19:35:09 +03:00
Michel Heily
8d612f3a36 Add %c formatting 2019-06-17 19:35:09 +03:00
Michel Heily
8e880b9bdd cformat: Fix a bug when formatting unicode strings
String::len() returns number of bytes and not number of chars, so it
doens't work as expected for unicode strings.

Also, added a test that would have triggered the bug.
2019-06-17 19:35:09 +03:00
Michel Heily
e374aff0bc Support '*' for width and precsision for printf-style formatting 2019-06-17 19:35:09 +03:00
Michel Heily
d5ffecea32 objstr: Improve errors for modulo format 2019-06-17 19:35:09 +03:00
Michel Heily
dc77728dbc cformat: Add some unittests.
Also, this commit fixes some bugs that were found using said unittests.
2019-06-17 19:35:09 +03:00
Michel Heily
481b044883 Support modulo formatting of numbers and string types 2019-06-17 19:35:09 +03:00
Michel Heily
fe6c1488d9 Start implementing str.__mod__ 2019-06-17 19:35:09 +03:00
Michel Heily
f27265cf8a Add get_value for objtuple 2019-06-17 19:35:09 +03:00
Michel Heily
d74e126246 Add parser for C printf-style format strings
This commit is a part of a series of future commits that will resolve #1007 .
Code is based on vm/src/format.rs.
2019-06-17 19:35:09 +03:00
Windel Bouwman
73edde66f7 Merge pull request #1037 from RustPython/coolreader18/option-source_path
Make CodeObject.source_path an Option<String>
2019-06-17 16:58:48 +02:00
rmliddle
8faab1f494 Implement String, BytesIO with Cursor<Vec<u8>> 2019-06-17 19:31:42 +10:00
coolreader18
b74b65d37e Make CodeObject.source_path an Option<String> 2019-06-16 19:59:04 -05:00
coolreader18
9b3521904a Update bench.rs to use vm.compile() 2019-06-16 15:47:27 -05:00
Windel Bouwman
8b0089e258 Merge pull request #1036 from RustPython/coolreader18/stdlib-mods-maplit
Use maplit::hashmap! for stdlib::get_module_inits()
2019-06-16 19:21:05 +02:00
coolreader18
b6b8f6ec9c Have stdlib::get_module_inits() use maplit::hashmap! 2019-06-16 10:33:47 -05:00
Windel Bouwman
ffeaf2d06a Merge pull request #1034 from RustPython/coolreader18/comptime-pycompilation
Allow compiling Python code to bytecode at compile-time
2019-06-16 17:28:02 +02:00
coolreader18
743adf10de Merge branch 'master' into coolreader18/comptime-pycompilation 2019-06-16 09:05:34 -05:00
coolreader18
d3927ff30e Merge pull request #1033 from palaviv/open-flags
Support more open flags
2019-06-16 00:34:45 -05:00
coolreader18
1814977c45 Add doc comments 2019-06-15 20:19:59 -05:00
coolreader18
6b9bbf3ea4 Change TODO 2019-06-15 13:23:04 -05:00
coolreader18
75c2e4ae9b Remove lazy_static, just store as a CodeObject 2019-06-15 11:31:30 -05:00
Aviv Palivoda
92ad30ef6a Add mode argument to os.open 2019-06-15 17:02:46 +03:00
Aviv Palivoda
82f83ef345 Support more open flags 2019-06-15 16:22:51 +03:00
coolreader18
241f5190cc Formatting 2019-06-15 00:30:14 -05:00
coolreader18
b5ba62fe94 Add lazy_static argument 2019-06-14 21:17:12 -05:00
coolreader18
48966a76e2 Make py_compile_bytecode!() an expression 2019-06-14 18:20:02 -05:00
coolreader18
7817cecc49 Merge pull request #1031 from palaviv/reversed
Support reversed on sequence
2019-06-14 15:23:35 -05:00
coolreader18
7e68f9924e Make Location's fields private again 2019-06-14 14:52:30 -05:00
coolreader18
4d0eb06724 Default source_path 2019-06-14 12:40:01 -05:00
coolreader18
d2cde9a3bf Use bincode to deserialize into a CodeObject 2019-06-14 12:26:35 -05:00
coolreader18
8143b69165 Change imp_get_frozen_object 2019-06-14 11:31:39 -05:00
coolreader18
9a09a92f31 Merge pull request #1030 from palaviv/import-from-list
Import all from_list in one call
2019-06-14 10:56:01 -05:00
coolreader18
e592f3d888 Add py_compile_bytecode! macro 2019-06-14 10:42:45 -05:00
Aviv Palivoda
60e799727f Support reversed on sequence 2019-06-14 15:25:24 +03:00
Aviv Palivoda
e61fa6dd74 Use Iterator to create from_list 2019-06-14 08:49:20 +03:00
Aviv Palivoda
4938c03d6f Improve compiler import 2019-06-14 08:45:30 +03:00
Aviv Palivoda
12a3028806 Import all from_list in one __import__ call 2019-06-14 08:27:49 +03:00
coolreader18
8b894a11fb Merge pull request #1029 from RustPython/coolreader18/rustpython_compiler
Split off bytecode compilation into a separate crate
2019-06-13 15:48:11 -04:00
coolreader18
bfd6145d5f Use RUSTPYTHONPATH in ouroboros instructions 2019-06-13 12:34:30 -05:00
coolreader18
c2502bf8ef Add doc comments and individual compile functions 2019-06-12 22:04:59 -05:00
coolreader18
45bb2bd263 Split off bytecode compilation into a separate crate 2019-06-12 21:43:43 -05:00
Windel Bouwman
3f343aff6c Merge pull request #1018 from palaviv/imp3
Importlib
2019-06-12 16:21:26 +02:00
coolreader18
02821324b7 Merge pull request #1028 from RustPython/coolreader18/update-deps1
Update cargo dependencies
2019-06-11 18:07:09 -05:00
coolreader18
cb2fe657a9 Merge pull request #1014 from mkurnikov/cleanup-get-method-error-handling
Cleanup get_method() error handling
2019-06-11 17:43:58 -05:00
coolreader18
07c6a90045 Update cargo dependencies 2019-06-11 16:00:35 -05:00
Aviv Palivoda
1de9f73bd0 Optimize already loaded modules 2019-06-11 22:54:54 +03:00
Windel Bouwman
50662c488a Merge pull request #968 from RustPython/walrus
Add walrus operator to lexer and try to make lexer code cleaner.
2019-06-11 15:06:04 +02:00
Aviv Palivoda
ea8e28026b Simplify objmodule 2019-06-11 13:13:32 +03:00
Aviv Palivoda
0e320f9af6 Change comment to XXX 2019-06-10 21:50:37 +03:00
Aviv Palivoda
603ef1ad05 Support from_list 2019-06-10 21:45:05 +03:00
Aviv Palivoda
e1472f2277 Add sys.dont_write_bytecode 2019-06-10 19:18:32 +03:00
Aviv Palivoda
03735a6d26 Add optional parameters to compile 2019-06-10 19:18:32 +03:00
Aviv Palivoda
8dec522f96 compile source may be bytes 2019-06-10 19:18:32 +03:00
Aviv Palivoda
10828e01fb Set sys.pycache_prefix to None 2019-06-10 19:18:32 +03:00
Aviv Palivoda
b567464378 Add ModuleNotFoundError to builtins 2019-06-10 19:18:32 +03:00
Aviv Palivoda
5df05d4f95 Add script dir to sys.path 2019-06-10 19:18:32 +03:00
Aviv Palivoda
d9d0ea1834 Fix os to _os in class 2019-06-10 19:18:32 +03:00
Aviv Palivoda
5584733cda Add sys.path_importer_cache 2019-06-10 19:18:32 +03:00
Aviv Palivoda
c8248c3211 Expose __name__ in __dict__ 2019-06-10 19:18:32 +03:00
Aviv Palivoda
375790e142 objmodule should have a dict 2019-06-10 19:18:32 +03:00
Aviv Palivoda
fe0284aa05 Add new to objmodule and change __name__ to property 2019-06-10 19:18:32 +03:00
Aviv Palivoda
6615e811c0 Collapse concat 2019-06-10 19:18:32 +03:00
Aviv Palivoda
5c53e58547 Print frozen import file name in stacktrace 2019-06-10 19:18:32 +03:00
Aviv Palivoda
0e76dbb749 Add needed methods to _thread 2019-06-10 19:18:32 +03:00
Aviv Palivoda
2817214c88 Remove unused imports 2019-06-10 19:18:32 +03:00
Aviv Palivoda
7f61125866 Use _bootstrap.py __import__ 2019-06-10 19:18:32 +03:00
Aviv Palivoda
58d9d9deeb Add sys.path_hooks 2019-06-10 19:18:32 +03:00
Aviv Palivoda
b0cccf35ad Change os_details 2019-06-10 19:18:32 +03:00
Aviv Palivoda
a57f38b07f Rename builtin io to _io 2019-06-10 19:18:32 +03:00
Aviv Palivoda
fbaff7fd50 Install external importers on init_importlib 2019-06-10 19:18:32 +03:00
Aviv Palivoda
37b40c55da Add frozen _bootstrap_external.py 2019-06-10 19:18:32 +03:00
Aviv Palivoda
0d9a066712 Add sys.meta_path 2019-06-10 19:18:32 +03:00
Aviv Palivoda
f2145880fa Don't set __file__ for frozen modules 2019-06-10 19:18:32 +03:00
Aviv Palivoda
f1af6b1f40 Include _bootstrap.py as str 2019-06-10 19:18:32 +03:00
Aviv Palivoda
698044b128 Add Module.__name__ 2019-06-10 19:18:32 +03:00
Aviv Palivoda
e88d6ac1ef Add init_importlib 2019-06-10 19:18:32 +03:00
Aviv Palivoda
7ff59b27d7 Add _bootsrap.py as frozen module 2019-06-10 19:18:32 +03:00
coolreader18
740e8387b8 Merge pull request #1027 from alanjds/format-bang
Feature: str.format accepting !r, !s and !a
2019-06-10 10:56:00 -05:00
rmliddle
33885a8334 Namespace added for objstr: get_value, PyStringRef 2019-06-10 22:48:28 +10:00
Alan Justino
854bacf452 Fix the Rust tests 2019-06-09 18:45:08 -03:00
Alan Justino
f0a2b4c50b Apply the {!r} on str.format calls
By the Python docs, the `!` forces a conversion of the argument before
applying the normal formating logic described after the `:` marker.

See: https://docs.python.org/3.4/library/string.html#format-string-syntax
2019-06-09 18:11:10 -03:00
Alan Justino
e19b674abf FormatSpec got a preconversor:FormatPreconversor to handle !r, !s and !a 2019-06-09 16:22:22 -03:00
coolreader18
68011df6cb Merge pull request #1024 from yanganto/str_isprintable
str.isprintable
2019-06-09 13:07:47 -05:00
Alan Justino
65d0093822 Dont fail on '{!r}'.format(...) 2019-06-09 13:46:13 -03:00
Antonio Yang
f76be43d26 str.isprintable
- check unicode type by unicode_categories
- rm redundant check of empty string
2019-06-09 23:33:38 +08:00
rmliddle
6542d3586e Optional args on new for Bytes/StringIO 2019-06-10 00:57:17 +10:00
rmliddle
6767b4efb1 BytesIO First Pass 2019-06-09 21:33:16 +10:00
Windel Bouwman
aa6b155e1e Merge branch 'master' of https://github.com/RustPython/RustPython into walrus 2019-06-09 11:49:02 +02:00
Windel Bouwman
1b968e9406 Merge pull request #1022 from RustPython/coolreader18/demo-repl-continuation
Add line continuation for the WASM demo terminal
2019-06-09 11:16:35 +02:00
coolreader18
d45c632f49 Add incompatibility issue template 2019-06-08 18:59:02 -05:00
coolreader18
b0db7c1096 Add RFC issue template
Structure taken from #771
2019-06-08 18:28:18 -05:00
coolreader18
cd61248635 Merge branch 'master' into coolreader18/demo-repl-continuation 2019-06-08 13:17:05 -05:00
Windel Bouwman
9d9fcfc034 Removal of walrus operator. 2019-06-08 16:38:15 +02:00
Windel Bouwman
9592e94920 Isolate determination of indentation into seperate method. 2019-06-08 16:23:51 +02:00
Windel Bouwman
eb234ca3c5 Merge pull request #1021 from mkurnikov/speed-up-file-open
Get io reader/writer classes only when needed
2019-06-08 16:13:42 +02:00
Windel Bouwman
a1e2da6807 Merge pull request #1020 from RustPython/coolreader18/no-pwd-android
Disable the pwd module on android
2019-06-08 16:12:23 +02:00
Maxim Kurnikov
baf62d56d2 get io reader/writer classes only when needed 2019-06-08 02:49:45 +03:00
coolreader18
2b555cb40e Merge pull request #1016 from mkurnikov/fix-io-open-r
Fix io.open("r") case and address some TODOs
2019-06-07 12:07:47 -05:00
coolreader18
50252b4e80 Disable the pwd module on android 2019-06-07 11:57:50 -05:00
coolreader18
d27840c11d Merge pull request #1019 from palaviv/warnings
Add _warnings
2019-06-07 11:45:48 -05:00
Aviv Palivoda
8fccad1e09 Print warning to stderr
Co-Authored-By: coolreader18 <33094578+coolreader18@users.noreply.github.com>
2019-06-07 18:59:41 +03:00
Maxim Kurnikov
c0e1702869 split mode/type for io.open properly, fix open('r') case 2019-06-07 16:34:16 +03:00
Maxim Kurnikov
8a5182a8a1 make get_method_or_type_error() error message lazy 2019-06-07 16:08:37 +03:00
Aviv Palivoda
d2a82b1acd Add _warnings 2019-06-07 15:14:27 +03:00
Windel Bouwman
1b7088c353 Merge pull request #1017 from michelhe/memoryview_obj
Fix memoryview.obj misimplementation.
2019-06-05 13:22:49 +02:00
coolreader18
74d52ee82f Merge pull request #1011 from palaviv/_imp2
More _imp
2019-06-05 00:43:10 -05:00
Michel Heily
b2cdeab0c6 Fix memoryview.obj misimplementation.
The memoryview skeleton did not correctly assign the "obj" attribute;
The "obj" attribute was assigned to the memoryview class and not the memryview object,
leading to a funny bug that can be reproduced as follows:

```python

m1 = memoryview(b'1234')
m2 = memoryview(b'abcd')

print(m1.obj)
```

the result would be the value inside `m2` instead that of `m1`
2019-06-05 02:36:45 +03:00
Windel Bouwman
0c9d3c8918 Merge pull request #1015 from mkurnikov/empty-exception-message
Make empty exception message format compatible with CPython
2019-06-04 15:52:47 +02:00
Maxim Kurnikov
bc33921fdb make empty exception message format compatible with CPython 2019-06-04 14:59:28 +03:00
Maxim Kurnikov
3bfd66bb89 make some exception messages more compatible with CPython, split get_method() into two methods and make raising TypeError more explicit for get_method() errors 2019-06-03 19:46:32 +03:00
Maxim Kurnikov
1b9c054d03 make new exception logs a bit more descriptive 2019-06-03 19:41:30 +03:00
coolreader18
e871ab0673 Merge pull request #1013 from mkurnikov/source-line-in-traceback
Add indented source lines in traceback
2019-06-02 23:05:59 -05:00
coolreader18
7ddfa1c4ce Merge pull request #1012 from mkurnikov/more-refactorings-2
More doc comments, split with_exit() method for __exit__ into two methods
2019-06-02 22:58:11 -05:00
Maxim Kurnikov
58b1f4a8ee add indented source line in traceback 2019-06-02 18:21:52 +03:00
Maxim Kurnikov
3b5cc1ad2f more doc comments, split with_exit() method for context manager __exit__ into two methods 2019-06-02 01:37:25 +03:00
Aviv Palivoda
106f5f7054 Add _imp.is_frozen_package 2019-06-01 15:15:16 +03:00
Aviv Palivoda
0acce07631 Add _imp.init_frozen 2019-06-01 15:11:55 +03:00
Aviv Palivoda
4faaf2d6ca Add _imp.get_frozen_object 2019-06-01 15:03:45 +03:00
Aviv Palivoda
9a168b10d1 Add _imp.exec_builtin that does nothing 2019-06-01 14:49:12 +03:00
Aviv Palivoda
1294b56cbe Add _imp.create_builtin 2019-06-01 14:32:23 +03:00
coolreader18
b6edd19331 Merge pull request #1010 from mkurnikov/fix-clippy-warnings
Fix most of clippy warnings
2019-05-31 20:19:49 -05:00
Maxim Kurnikov
bc35a64e54 fix most of clippy warnings 2019-06-01 03:19:22 +03:00
Windel Bouwman
e0dbfb553f Merge pull request #1009 from mkurnikov/refactorings
Some cleanups and typo fixes
2019-05-31 22:25:52 +02:00
Maxim Kurnikov
1949239592 cleanups, type fixes and renames 2019-05-31 21:56:10 +03:00
Windel Bouwman
849c6eb1ee Merge pull request #995 from stwen77/binascii
add binascii crc32
2019-05-31 09:30:19 +02:00
Windel Bouwman
8a9e6ef0de Merge pull request #1008 from RustPython/coolreader18/cpython-libs1
Update Lib/operator.py and add Lib/heapq.py from cpython
2019-05-31 09:27:16 +02:00
stwen77
e9f3f4b89a Merge branch 'master' into binascii 2019-05-31 14:22:42 +08:00
Shitong Wen
e452d5523e use crate crc to replace crc table 2019-05-31 14:16:31 +08:00
coolreader18
39c63ef139 Update Lib/operator.py and add Lib/heapq.py from cpython 2019-05-30 23:04:09 -05:00
Aviv Palivoda
9e88b808dd Add _imp.is_frozen 2019-05-30 18:50:46 +03:00
Windel Bouwman
15f94679c4 Merge pull request #988 from skinny121/sys_flags
Add sys.flags
2019-05-30 12:24:04 +02:00
ben
d2757a2680 Fix merge issue with PyTuple::fast_getitem 2019-05-30 21:22:30 +12:00
ben
c0c531d550 Merge branch 'master' into sys_flags
# Conflicts:
#	tests/snippets/sysmod.py
#	vm/src/sysmodule.rs
2019-05-30 21:12:57 +12:00
Windel Bouwman
3f5bb517a5 Merge pull request #1001 from RustPython/coolreader18/rustpythonpath
Check RUSTPYTHONPATH as well as PYTHONPATH env variables
2019-05-30 09:53:05 +02:00
Windel Bouwman
22b4894ae6 Merge pull request #1006 from RustPython/coolreader18/weakproxy-setattr
Add __setattr__ to weakproxy
2019-05-30 09:47:01 +02:00
coolreader18
725a1e8434 Merge pull request #979 from youknowone/refactor-set
PySet/PyFrozenSet refactoring
2019-05-29 23:38:56 -05:00
coolreader18
1dc2d09713 Add __setattr__ to weakproxy 2019-05-29 22:46:12 -05:00
coolreader18
7ae33b72cb Merge pull request #1005 from Jongy/lib-reprlib
Lib reprlib
2019-05-29 22:08:57 -05:00
coolreader18
c78dc520ad Don't clone PathBufs 2019-05-29 16:53:13 -05:00
coolreader18
11892816a7 Don't check env variables on wasm 2019-05-29 16:38:04 -05:00
Yonatan Goldschmidt
7ec3cef48e Add Lib/reprlib.py from CPython
Generated with:
`git -C ../cpython show 1bf9cc509326bc42cd8cb1650eb9bf64550d817e:Lib/reprlib.py > Lib/reprlib.py`

Required for `functools`.
2019-05-30 00:15:11 +03:00
coolreader18
1846100e7f Merge pull request #969 from Jongy/itertools-islice
itertools islice
2019-05-29 16:08:48 -05:00
Yonatan Goldschmidt
80b1f545e2 Add itertools.islice 2019-05-29 23:25:49 +03:00
Windel Bouwman
d70caf7dea Merge pull request #960 from youknowone/sys-getfilesystemencode
Add sys.getfilesystemencoding, sys.getfilesystemencodeerrors
2019-05-29 15:21:19 +02:00
Windel Bouwman
121cd43932 Merge pull request #901 from youknowone/str-encode
Add str.encode for utf-8
2019-05-29 15:20:36 +02:00
Jeong YunWon
c349f77207 Add {set,frozenset}.__r*__ 2019-05-29 21:51:20 +09:00
Jeong YunWon
ba4ac902eb PySet/PyFrozenSet doesn't call PyObject::new 2019-05-29 21:51:20 +09:00
Jeong YunWon
979e1253ae Fix set/frozenset comparison 2019-05-29 21:51:20 +09:00
Jeong YunWon
31c88721e6 Refactor PySet with try_set_inner! 2019-05-29 21:51:20 +09:00
Jeong YunWon
89729c3155 PyClassImpl for PySet, PyFrozenSet 2019-05-29 21:51:20 +09:00
coolreader18
5bd36ad9c5 Merge pull request #927 from youknowone/set-collision
Fix set() hash collision
2019-05-29 07:44:31 -05:00
Jeong YunWon
59476c65bb PyBytes::from_string 2019-05-29 21:27:58 +09:00
Jeong YunWon
7f2560c9e1 Add str.encode for utf-8 2019-05-29 21:25:34 +09:00
jgirardet
ad357d08af normalize_encoding 2019-05-29 21:24:51 +09:00
Jeong YunWon
3675ce859a Add sys.getfilesystemencoding, sys.getfilesystemencodeerrors 2019-05-29 21:20:55 +09:00
Windel Bouwman
f113342c0c Merge pull request #1002 from RobertBerglund/bytearray.__setitem__
bytearray.__setitem__
2019-05-29 13:48:58 +02:00
rbrtberglund
eed9c44a74 improved PyByteInner.setitem 2019-05-29 00:02:58 +02:00
coolreader18
d2fdb3258a Merge branch 'master' into coolreader18/rustpythonpath 2019-05-28 16:25:47 -05:00
Windel Bouwman
d9be5aba35 Merge pull request #1004 from DanielShaulov/marshal_support
Add support for marshal with loads and dumps
2019-05-28 12:12:35 +02:00
rbrtberglund
9b4b2d7fa6 fixed SyntaxError: Got unexpected EOF in bytearray.py 2019-05-27 22:48:25 +02:00
rbrtberglund
7be801db2f implemented __setitem__ for bytearray 2019-05-27 22:22:20 +02:00
Daniel Shaulov
bd89c4e32b Reformat with rustfmt 2019-05-27 22:19:07 +03:00
Daniel Shaulov
b2f17a18ea Add support for marshal with loads and dumps 2019-05-27 22:09:47 +03:00
coolreader18
96df472d85 Merge pull request #999 from palaviv/_imp
Add _imp
2019-05-26 13:53:21 -05:00
Aviv Palivoda
042a673ea2 Use contains_key 2019-05-26 21:16:40 +03:00
coolreader18
770f54791e Fix ownership errors 2019-05-25 17:28:25 -05:00
coolreader18
017377061d Check RUSTPYTHONPATH as well as PYTHONPATH env variables 2019-05-25 15:52:44 -05:00
coolreader18
7ce111b16c Merge pull request #997 from ZapAnton/objstr_refactor_mul
objstr: Refactored the 'mul' method
2019-05-25 12:11:44 -05:00
coolreader18
d0d4cb56c5 Merge pull request #998 from palaviv/frozen
Support frozen modules
2019-05-25 12:10:11 -05:00
ZapAnton
a2e64c0425 objstr: Replaced the unwrap_or with the OverflowError 2019-05-25 16:38:51 +03:00
Aviv Palivoda
7a467781e2 Add _imp.is_builtin 2019-05-25 15:34:18 +03:00
Aviv Palivoda
8197b17c14 Add empty _imp locks methods 2019-05-25 15:07:51 +03:00
Aviv Palivoda
2c74d7cc12 Add _imp 2019-05-25 15:02:03 +03:00
Aviv Palivoda
f33d15ab6a Test frozen modules import 2019-05-25 11:15:17 +03:00
Aviv Palivoda
a38f205f0e Add support for frozen modules 2019-05-25 11:13:25 +03:00
ZapAnton
e38c54985e objstr: Replaced the if-else construct with the max function 2019-05-24 20:37:47 +03:00
ZapAnton
fedbd29051 objstr: Refactored the 'mul' method
- Used `str::repeat` instead of manually building the result string
- Rewritten the int type check to return error at the beginning of the
method
- Replaced the `unwrap` calls with the single `unwrap_or`
2019-05-24 13:01:15 +03:00
Windel Bouwman
606a336fdf Merge pull request #996 from palaviv/io-context
RawIOBase inherits IOBase
2019-05-24 11:03:13 +02:00
Aviv Palivoda
8afb6a201c RawIOBase inherits IOBase 2019-05-24 10:23:30 +03:00
Shitong Wen
813c6112e6 add crc32 test 2019-05-23 16:30:19 +08:00
Shitong Wen
21bffc8ffa add crc32 test 2019-05-23 16:11:17 +08:00
Shitong Wen
fdd569cb8b add crc32 2019-05-23 16:08:12 +08:00
stwen77
95ddd55081 Merge pull request #4 from RustPython/master
refresh
2019-05-22 19:20:44 +08:00
Windel Bouwman
61e752e2b0 Merge pull request #994 from mkurnikov/simplify-with-cloned
Simplify PyFuncArgs get_kwarg/get_optional_kwarg with cloned()
2019-05-22 13:02:50 +02:00
Maxim Kurnikov
737ec52365 simplify PyFuncArgs get_kwarg/get_optional_kwarg with cloned() 2019-05-22 12:47:28 +03:00
Windel Bouwman
59fa46d5c3 Merge pull request #977 from adrian17/master
Fix no-arg dir(), convert it to new args style
2019-05-22 11:20:33 +02:00
Windel Bouwman
6b3b132343 Merge pull request #993 from mkurnikov/move-to-indexmap
Move PyFuncArgs.kwargs to IndexMap, implement PEP-468
2019-05-22 11:17:51 +02:00
Maxim Kurnikov
b5352da2c0 fix formatting 2019-05-22 03:30:30 +03:00
Maxim Kurnikov
0098e8485a move PyFuncArgs.kwargs to IndexMap 2019-05-22 03:18:15 +03:00
coolreader18
9ff9404ec8 Merge pull request #992 from sanxiyn/fix-rsplit
Fix rsplit
2019-05-21 09:48:14 -05:00
Seo Sanghyeon
433434a1bb Fix rsplit 2019-05-21 23:01:04 +09:00
Windel Bouwman
5ff766adb6 Merge pull request #976 from sanxiyn/pwd
Implement pwd module
2019-05-21 14:49:30 +02:00
Windel Bouwman
c01a867da5 Merge pull request #974 from stwen77/add_int_to_bytes
Add to_bytes for int
2019-05-21 14:47:31 +02:00
Windel Bouwman
002140ad69 Merge pull request #991 from Jongy/tuple-remove-refcell
Remove RefCell from tuple
2019-05-21 14:46:20 +02:00
Yonatan Goldschmidt
84684e5f7d Don't use RefCell in tuple object 2019-05-19 23:57:32 +03:00
coolreader18
1ea0192ea3 Merge pull request #986 from Jongy/itertools-chain
Add `itertools.chain`
2019-05-19 15:30:07 -05:00
coolreader18
347d9e7510 Merge pull request #985 from RobertBerglund/exit
Add exit/quit builtin function
2019-05-19 15:24:34 -05:00
Yonatan Goldschmidt
802f07980e Remove tuple handling from get_elements_cell
Like my HEAD, this shouldn't be allowed for a tuple (and the
only call-site of this function doesn't run on tuples anyway).
2019-05-19 23:01:10 +03:00
Yonatan Goldschmidt
9ad527c800 Remove tuple handling from get_mut_elements
This function is unused anyway; But even was it used, it makes no sense
to return mutable references to tuple items, when the tuple holding them
is immutable.
2019-05-19 23:01:05 +03:00
Yonatan Goldschmidt
9bf386ea87 Add itertools.chain 2019-05-19 22:33:47 +03:00
coolreader18
bb14858f03 Merge branch 'master' of github.com:RustPython/RustPython 2019-05-19 14:05:23 -05:00
coolreader18
0cb1b73714 Merge branch 'palaviv-move-fspath' 2019-05-19 14:05:13 -05:00
coolreader18
8f8194ae13 Fix os.rs 2019-05-19 14:05:09 -05:00
coolreader18
0c19cf0d25 Merge branch 'move-fspath' of https://github.com/palaviv/RustPython into palaviv-move-fspath 2019-05-19 14:03:20 -05:00
coolreader18
297e507197 Merge pull request #990 from skinny121/simple_namespace
Add SimpleNamespace and sys.implementation
2019-05-19 14:02:24 -05:00
coolreader18
4ada5bf530 Merge pull request #972 from sanxiyn/re-escape
Implement re.escape
2019-05-19 13:20:22 -05:00
Adrian Wielgosik
1e7fa52e0f Fix no-arg dir(), convert it to new args style 2019-05-19 12:27:08 +02:00
Seo Sanghyeon
347d1fd240 Enable pwd module only on Unix 2019-05-19 13:16:37 +09:00
Seo Sanghyeon
36412c57a4 Implement pwd module 2019-05-19 12:52:38 +09:00
coolreader18
a967171ed9 Merge pull request #989 from sanxiyn/update-rustyline
Update rustyline to 4.1.0 to fix nightly build
2019-05-18 22:35:37 -05:00
Ben Lewis
964256439b Update vm/src/obj/objnamespace.rs
Co-Authored-By: coolreader18 <33094578+coolreader18@users.noreply.github.com>
2019-05-19 15:25:52 +12:00
ben
52039845dd Use closure for generated properties in struct sequences. 2019-05-19 15:23:51 +12:00
ben
60c9d5004a Add SimpleNamespace and sys.implementation 2019-05-19 15:01:22 +12:00
Seo Sanghyeon
b9814ce3c7 Update rustyline to 4.1.0 to fix nightly build 2019-05-19 12:00:36 +09:00
rbrtberglund
bb93977a7e applied suggestions to improve exit function implementation 2019-05-19 00:42:55 +02:00
ben
8b657ab81e Add documentation for sys.flags 2019-05-19 10:32:07 +12:00
ben
2ca96c8ae1 Add sys.flags by creating a pystruct_sequence macro 2019-05-19 10:17:21 +12:00
coolreader18
8359c6e031 Merge pull request #983 from ypyf/type_new
improve error message for type_new
2019-05-18 17:12:43 -05:00
coolreader18
b5fa32ec95 Merge pull request #987 from Jongy/itertools-starmap
Add `itertools.starmap`
2019-05-18 16:31:58 -05:00
Yonatan Goldschmidt
7f310bd81f Add itertools.starmap 2019-05-18 23:53:40 +03:00
rbrtberglund
cb0367e708 Add exit/quit builtin function 2019-05-18 16:14:43 +02:00
coolreader18
9ee3bad3c1 Merge pull request #984 from sanxiyn/fix-wasm-test
Avoid timeout in WASM test
2019-05-17 12:12:41 -05:00
Seo Sanghyeon
b76da2ad05 Avoid timeout in WASM test 2019-05-17 18:58:59 +09:00
coolreader18
9888d27e61 Merge pull request #981 from youknowone/frexp
Add math.frexp
2019-05-16 21:37:34 -05:00
coolreader18
23344ddf8a Merge pull request #982 from youknowone/float-fromhex
Add float.fromhex float.hex
2019-05-16 21:33:40 -05:00
coolreader18
8759e7e513 Merge pull request #980 from youknowone/complex-hash
Add complex.__hash__
2019-05-16 21:25:46 -05:00
Jeong YunWon
ca912a168d Add float.to_hex 2019-05-17 03:24:31 +09:00
Jeong YunWon
ceca2ed98e Add float.fromhex 2019-05-17 02:35:39 +09:00
Jeong YunWon
d223af645b Add math.frexp 2019-05-17 01:12:43 +09:00
ypyf
83c5a3d330 improve error message for type_new 2019-05-16 20:35:40 +08:00
Jeong YunWon
87fc4cc470 Add complex.__hash__ 2019-05-16 06:21:33 +09:00
Jeong YunWon
81186ea5b7 Fix set() hash collision based on dictdatatype::Dict 2019-05-16 00:02:39 +09:00
Jeong YunWon
cc9dcbc9f8 Refactor dictdatatype::Dict 2019-05-16 00:01:44 +09:00
Jeong YunWon
13187fad5c Fix dictdatatype::Dict eq to regard __bool__ 2019-05-15 23:25:05 +09:00
coolreader18
54152b877b Merge pull request #970 from sanxiyn/remove-types
Replace types module with pure Python version
2019-05-14 20:46:17 -05:00
Shitong Wen
68a1a9f648 add to_bytes for int 2019-05-14 16:56:50 +08:00
coolreader18
15d2a3d318 Merge pull request #973 from sanxiyn/remove-extern-crate
Remove extern crate unneeded for Rust 2018
2019-05-13 23:51:37 -05:00
Seo Sanghyeon
189bf171ab Remove extern crate unneeded for Rust 2018 2019-05-14 12:24:44 +09:00
Seo Sanghyeon
5cff843782 Implement re.escape 2019-05-13 19:41:06 +09:00
Adam
2c747168de Merge pull request #926 from youknowone/number-hashes
Fix number hashes for small numbers
2019-05-13 09:02:19 +01:00
Windel Bouwman
0e56bb4e8c Merge pull request #965 from Jongy/itertools-takewhile
Itertools takewhile
2019-05-13 08:13:11 +02:00
coolreader18
82e424acaa Merge branch 'master' into move-fspath 2019-05-12 21:46:43 -05:00
Seo Sanghyeon
b76cb680e9 Comment out unsupported code from types.py 2019-05-13 11:44:12 +09:00
Seo Sanghyeon
b048a66bc3 Copy types.py from CPython 2019-05-13 11:42:16 +09:00
Seo Sanghyeon
29fff5ab4d Remove types module 2019-05-13 11:41:46 +09:00
stwen77
0cd1ca5f80 Merge pull request #3 from RustPython/master
pull
2019-05-13 10:41:28 +08:00
coolreader18
b01d7564b8 Merge pull request #964 from youknowone/os-supports-placeholders
Add os.supports_* placeholders
2019-05-12 16:23:38 -05:00
Windel Bouwman
b8c788197e Add walrus operator to lexer and try to make lexer code cleaner. 2019-05-12 22:35:28 +02:00
Yonatan Goldschmidt
98d90c830b Add itertools.takewhile 2019-05-12 23:16:23 +03:00
Jeong YunWon
64afd5ccf8 Add os.supports_* placeholders 2019-05-13 01:15:19 +09:00
Jeong YunWon
7a64f3e797 Fix dict hash impl 2019-05-13 01:10:54 +09:00
Jeong YunWon
c768b25673 Refine hash types and refactor hash impl 2019-05-13 01:10:52 +09:00
Jeong YunWon
3bebe44896 Fix int.__hash__ 2019-05-13 01:09:51 +09:00
Jeong YunWon
2c77dc208f Add float.__hash__ 2019-05-13 01:09:51 +09:00
Jeong YunWon
72043dac99 Fix builtin hash() 2019-05-13 01:09:51 +09:00
Windel Bouwman
95a894a443 Merge pull request #954 from youknowone/property-kwargs
Fix property to take keyword arguments
2019-05-12 16:15:01 +02:00
Windel Bouwman
e1416f5ecc Merge pull request #967 from skinny121/str_xwith_tuple_arg
Accept tuple for first arg in str.startswith and str.endswith
2019-05-12 16:13:25 +02:00
Windel Bouwman
5273bdc836 Merge pull request #955 from youknowone/sys-builtin_module_names
Add sys.builtin_module_names
2019-05-12 15:07:45 +02:00
Windel Bouwman
878cc3b120 Merge pull request #943 from Furyzer0/master
[WIP] implement str.translate and str.maketrans
2019-05-12 15:04:31 +02:00
Windel Bouwman
41f4cdc6f9 Merge pull request #952 from youknowone/fix-exec-locals
Fix exec to populate locals only when globals() is not given
2019-05-12 15:03:01 +02:00
Windel Bouwman
b5140a9924 Merge pull request #953 from youknowone/classmethod-func
Add classmethod.__func__
2019-05-12 12:53:26 +02:00
Jeong YunWon
ddf676569a Add sys.builtin_module_names 2019-05-12 19:18:37 +09:00
Jeong YunWon
e311b4f156 Fix exec to populate locals only when globals() is not given 2019-05-12 19:15:39 +09:00
zer0
04c017d268 unit testing for str.maketrans 2019-05-12 12:47:23 +03:00
Windel Bouwman
0a1399a42b Merge pull request #962 from skinny121/os_stat_time
Add st_{a,m,c}time to os.stat
2019-05-12 11:42:57 +02:00
Windel Bouwman
937704fbd9 Merge pull request #881 from youknowone/globals-builtins
Add __builtins__ to globals()
2019-05-12 11:40:07 +02:00
Windel Bouwman
9f39fa50c8 Merge pull request #949 from Jongy/itertools-repeat
Itertools repeat
2019-05-12 11:36:35 +02:00
Windel Bouwman
2261988648 Merge pull request #948 from Jongy/itertools
Itertools
2019-05-12 11:34:22 +02:00
ben
90711f10a0 Accept tuple for first arg in str.startswith and str.endswith 2019-05-12 13:14:27 +12:00
zer0
764215151d more idiomatic code 2019-05-12 00:40:43 +03:00
zer0
b94923314d removed import warning 2019-05-12 00:00:21 +03:00
zer0
268cb8d217 fix str.maketrans 2 and 3 arguments cases 2019-05-11 23:58:42 +03:00
ben
645c6dec48 Add wait between file modification and access 2019-05-12 08:55:39 +12:00
ben
f2703511b9 Fix dead code warning on windows and disable access time tests
as file access time on windows has quite bad resolution.
2019-05-12 08:26:37 +12:00
ben
4070baa6ac Add fsync and more tests for file times 2019-05-12 07:51:14 +12:00
coolreader18
9dcfacbf3b Merge pull request #963 from palaviv/sys-platform
Add sys.platform
2019-05-11 13:50:46 -05:00
Aviv Palivoda
d96d04f0fd Add os.fspath tests 2019-05-11 18:08:47 +03:00
Aviv Palivoda
b54354860f Move fspath to _os 2019-05-11 18:06:06 +03:00
Aviv Palivoda
d1c95d1c51 Remove patch in posixpath.py 2019-05-11 17:17:00 +03:00
Windel Bouwman
c276357c8e Merge pull request #961 from palaviv/os-cwd
os.{getcwd,chdir}
2019-05-11 14:45:07 +02:00
Windel Bouwman
57e250f9b2 Merge pull request #957 from Jongy/binascii
Binascii
2019-05-11 14:43:08 +02:00
Yonatan Goldschmidt
12e831380d Add itertools.repeat 2019-05-11 15:42:11 +03:00
Windel Bouwman
ad86bd5a37 Merge pull request #951 from youknowone/str-isidentifier
Fix str.isidentifier() and add tests snippets
2019-05-11 14:35:38 +02:00
Yonatan Goldschmidt
322aff70df Add binascii.b2a_hex, binascii.a2b_hex 2019-05-11 12:01:35 +03:00
Yonatan Goldschmidt
070529d8c7 Add binascii.unhexlify 2019-05-11 12:01:35 +03:00
Yonatan Goldschmidt
8dd664ef20 Add binascii.hexlify 2019-05-11 12:01:35 +03:00
Yonatan Goldschmidt
f7531d8b08 Add binascii module skeleton 2019-05-11 11:57:46 +03:00
Yonatan Goldschmidt
ce514d2aa5 Add itertools.count 2019-05-11 11:48:27 +03:00
Yonatan Goldschmidt
7490724b65 Add itertools module skeleton 2019-05-11 11:48:26 +03:00
Aviv Palivoda
152c1654d6 Add sys.platform 2019-05-11 11:43:11 +03:00
ben
b01e960da7 Add st_{a,m,c}time to os.stat 2019-05-11 19:15:54 +12:00
Aviv Palivoda
c7e9bdd464 Add tests for chdir and getcwd 2019-05-11 09:29:24 +03:00
Aviv Palivoda
f0fd371b69 Add os.chdir 2019-05-11 09:29:09 +03:00
Aviv Palivoda
8294ac5451 Add os.getcwd 2019-05-11 09:17:23 +03:00
Jeong YunWon
c0f14eace3 Fix str.isidentifier() and add tests snippets 2019-05-11 14:30:47 +09:00
zer0
6e05795521 added str.maketrans 2019-05-11 01:03:22 +03:00
Jeong YunWon
268164e957 Fix property to take keyword arguments 2019-05-11 06:03:53 +09:00
Jeong YunWon
eab5d42ee6 Adapt PyClassImpl for PyProperty 2019-05-11 06:03:45 +09:00
zer0
b15a584168 added small test to snippets 2019-05-10 23:47:11 +03:00
zer0
2f253ca054 cargo fmt 2019-05-10 23:31:11 +03:00
Jeong YunWon
7564833b6e Add classmethod.__func__ 2019-05-11 05:30:27 +09:00
Jeong YunWon
b720681c7b PyClassImpl for PyClassMethod 2019-05-11 05:30:27 +09:00
Jeong YunWon
509394080b Inject __builtins__ to scope only when it doesn't exist 2019-05-11 03:05:18 +09:00
Jeong YunWon
f69c79bdc7 Add __builtins__ to globals() 2019-05-11 01:17:22 +09:00
coolreader18
0a683f2be6 Merge pull request #946 from stwen77/fix_floor_div
fix floor div for int
2019-05-10 08:25:24 -05:00
coolreader18
385d4851d1 Merge pull request #942 from Jongy/fix-unused-macros-warn
Define `os_unix_stat_inner` only when required
2019-05-10 08:00:20 -05:00
Windel Bouwman
d14fb6edbb Merge pull request #947 from palaviv/file
Support __file__
2019-05-10 14:41:12 +02:00
Aviv Palivoda
fc1a063a2c Add __file__ for file executed from main 2019-05-10 14:06:23 +03:00
Aviv Palivoda
da3df8a0ae Add __file__ for imported modules 2019-05-10 13:58:10 +03:00
Yonatan Goldschmidt
fe37ecf8d3 Define os_unix_stat_inner only when required
Avoids warn when building on Windows.
2019-05-10 11:24:28 +03:00
Shitong Wen
50c119a503 fix floor div for int 2019-05-10 14:21:09 +08:00
Windel Bouwman
352bd85681 Merge pull request #944 from sapir/more-bytearray-methods
More bytearray methods
2019-05-10 07:06:30 +02:00
stwen77
bc6e3eb0c4 Merge pull request #2 from RustPython/master
refresh
2019-05-10 10:37:26 +08:00
Y. Sapir
32950bd0bc Implement bytearray.reverse 2019-05-10 00:33:14 +03:00
Y. Sapir
e5bae56ccb Implement bytearray.remove 2019-05-10 00:33:14 +03:00
Y. Sapir
43cd50270f Implement bytearray.insert 2019-05-10 00:33:14 +03:00
Y. Sapir
485ffa01a2 Implement bytearray.extend 2019-05-10 00:33:14 +03:00
Y. Sapir
04ce9ea185 Implement bytearray.copy 2019-05-10 00:33:12 +03:00
Y. Sapir
87844ff434 Implement bytes.__mul__ and __rmul__ 2019-05-09 23:51:20 +03:00
Y. Sapir
94d1b6585c Implement bytearray.__mul__, __imul__ and __rmul__ 2019-05-09 23:50:20 +03:00
Windel Bouwman
e974e57b4c Merge pull request #941 from stwen77/int_from_bytes
add from_bytes for int
2019-05-09 16:57:36 +02:00
zer0
59ae590771 formatting 2019-05-09 17:09:38 +03:00
zer0
3196b6be73 added str.translate 2019-05-09 16:59:40 +03:00
coolreader18
76a0020e26 Merge pull request #940 from sanxiyn/test-all-any
Test all and any
2019-05-09 07:37:16 -05:00
Shitong Wen
86fcc97730 int_from_bytes 2019-05-09 20:06:28 +08:00
Seo Sanghyeon
d3966af25d Test all and any 2019-05-09 15:54:07 +09:00
Shitong Wen
e9fea281fb add from_bytes for int 2019-05-09 11:02:34 +08:00
Shitong Wen
036b184dd3 add from_bytes for int 2019-05-09 10:52:10 +08:00
stwen77
bdb9445e93 Merge pull request #1 from RustPython/master
pull
2019-05-09 10:34:09 +08:00
coolreader18
252ac4ae26 Merge pull request #938 from sanxiyn/revert-mappingproxy
Revert mappingproxy hack
2019-05-08 21:04:47 -05:00
Seo Sanghyeon
7d0ab6395b Revert mappingproxy hack 2019-05-09 09:45:41 +09:00
coolreader18
80e9bd8ab6 Merge pull request #931 from jgirardet/title
add bytes/byterray title
2019-05-08 12:13:59 -05:00
jgirardet
4c09505865 Merge branch 'master' into title 2019-05-08 18:16:02 +02:00
coolreader18
099b1f4752 Merge pull request #936 from palaviv/os-path
Os path
2019-05-08 10:44:08 -05:00
Aviv Palivoda
f5653cbc68 Use supported raise from 2019-05-08 16:47:49 +03:00
Aviv Palivoda
216f69e635 Use os.path 2019-05-08 16:46:45 +03:00
Aviv Palivoda
ac9ddf7756 Add CPython ntpath.py 2019-05-08 16:32:09 +03:00
Aviv Palivoda
daae7aa998 Add CPython posixpath.py 2019-05-08 16:31:21 +03:00
Aviv Palivoda
6153e2d6ca Add CPython genericpath.py 2019-05-08 16:25:33 +03:00
Windel Bouwman
6f31cf7554 Merge pull request #913 from Jongy/str-preallocate-and-rmul
Preallocate strings in a smarter way + add str.rmul
2019-05-07 21:54:31 +02:00
Windel Bouwman
382e566315 Merge pull request #930 from jgirardet/byteraayfollow
add split, rsplit, partition, rpartition, expandtabs, spitlines, zfill,replace to bytearray
2019-05-07 21:50:39 +02:00
Windel Bouwman
d76e4d5433 Merge pull request #934 from Jongy/range-arg3-zero
Raise an error on `range()` with step=0
2019-05-07 21:30:00 +02:00
Windel Bouwman
c9ba9192f6 Merge pull request #922 from palaviv/os-symlink
Symlinks
2019-05-07 21:28:46 +02:00
Windel Bouwman
aed8e03473 Merge pull request #932 from youknowone/dict-unpacking
Add dict unpacking support for literal
2019-05-07 21:25:39 +02:00
coolreader18
7727d09691 Merge pull request #933 from Jongy/nameerror-on-bad-del
Nameerror on bad del
2019-05-07 13:31:58 -05:00
Yonatan Goldschmidt
d4a3d7eb01 Raise an error on range() with step=0 2019-05-06 23:23:48 +03:00
Jeong YunWon
e12c6813ef Add dict unpacking support for literal 2019-05-07 04:42:58 +09:00
Yonatan Goldschmidt
04bff49ee0 Raise proper NameError on del when name is not defined
Closes #929.
2019-05-06 22:40:00 +03:00
jgirardet
dc18356947 add bytes/byterray title 2019-05-06 21:37:15 +02:00
jgirardet
ed94ddba2d add split, rsplit, partition, rpartition, expandtabs, spitlines, zfill,
replace to bytearray
2019-05-06 21:04:09 +02:00
Yonatan Goldschmidt
e35dec64f9 Add vm.new_name_error helper 2019-05-06 21:47:18 +03:00
Windel Bouwman
abf0a329ee Merge pull request #924 from Jongy/builtin-ord-improvements
Builtin ord improvements
2019-05-06 18:14:23 +02:00
Windel Bouwman
7ae533f860 Merge pull request #911 from sapir/fix-clippy-float-error
Fix clippy error about float comparison
2019-05-06 18:12:25 +02:00
Windel Bouwman
567fc4e94f Merge pull request #916 from jgirardet/bytergevalue
rewrite pybytearray with pybyteinner
2019-05-06 18:09:12 +02:00
Windel Bouwman
68d1fb8957 Merge pull request #915 from jgirardet/split
add  bytes split, expendtab, splitlines, zfil, replace
2019-05-06 17:46:43 +02:00
Windel Bouwman
720f2fed44 Merge pull request #925 from Jongy/builtin-chr-raise-error
Raise error on out-of-range input in `chr()`
2019-05-06 17:38:25 +02:00
Yonatan Goldschmidt
c656c5cc72 Add chr() test snippets 2019-05-06 03:10:53 +03:00
Yonatan Goldschmidt
ea535856b4 Raise error on out-of-range input in chr() 2019-05-06 03:04:19 +03:00
jgirardet
5a95c5af22 remove unittests 2019-05-05 23:29:49 +02:00
Windel Bouwman
51245639ab Merge pull request #923 from youknowone/floatint-format
str(1.0) == '1.0'
2019-05-05 21:18:43 +02:00
Windel Bouwman
e1bdae000c Merge pull request #904 from RustPython/async-stuff
Add async def and async for parsing.
2019-05-05 21:16:29 +02:00
Aviv Palivoda
ecd6e85f3c Fix windows build try 2 2019-05-05 21:32:49 +03:00
Aviv Palivoda
c06b6ccc96 Fix windows build 2019-05-05 21:19:20 +03:00
Yonatan Goldschmidt
6a73790b26 Raise proper error when string of length 0 is given to ord() 2019-05-05 20:24:54 +03:00
Yonatan Goldschmidt
717c96837e Borrow instead of cloning in ord() 2019-05-05 20:24:20 +03:00
Jeong YunWon
6b495eac1e str(1.0) == '1.0' 2019-05-06 02:14:28 +09:00
Aviv Palivoda
2c30e83896 Add follow_symlinks to stat 2019-05-05 20:04:39 +03:00
Aviv Palivoda
260af4d877 Add follow_symlinks to DirEntry.{is_file, is_dir} 2019-05-05 19:40:01 +03:00
Aviv Palivoda
914f32afc3 Add symlink tests 2019-05-05 19:17:30 +03:00
Aviv Palivoda
5bd23b4fb6 is_dir and is_file follow_symlink by default 2019-05-05 19:14:34 +03:00
Windel Bouwman
6228a207e1 Merge pull request #912 from sapir/repl-underscore
Repl underscore
2019-05-05 11:21:20 +02:00
coolreader18
de6bc057fb Merge pull request #919 from sapir/check-parent-equiv
Include reimplemented methods in whats_left.sh, and skip inherited methods
2019-05-04 19:11:48 -05:00
Y. Sapir
c38a3711d0 Include reimplemented methods in whats_left.sh, and skip inherited methods 2019-05-05 00:05:13 +03:00
Y. Sapir
88c3852b73 Don't check for methods on iter - it's a builtin function 2019-05-05 00:02:10 +03:00
Windel Bouwman
ee2b2a82fc Merge pull request #909 from sapir/add-bool-methods
Add bool methods
2019-05-04 22:34:43 +02:00
Windel Bouwman
a36fb77d42 Merge pull request #910 from sapir/print-file-parameter
Print file parameter
2019-05-04 22:33:55 +02:00
Y. Sapir
1a5bddc41b Fix clippy error about float comparison 2019-05-04 23:32:49 +03:00
Aviv Palivoda
6225de3098 Change file attributes to consts 2019-05-04 23:15:22 +03:00
Y. Sapir
bbb8df797f Refactor builtin_print to avoid duplicate loop code 2019-05-04 22:55:20 +03:00
Y. Sapir
ad2499f432 Implement print file parameter 2019-05-04 22:55:20 +03:00
Y. Sapir
4cce44ab31 Add test for print file parameter 2019-05-04 22:55:20 +03:00
Y. Sapir
45d7c383cd Implement bool.__ror__, __rand__ and __rxor__ 2019-05-04 22:27:43 +03:00
Windel Bouwman
c217685eeb Merge pull request #918 from palaviv/except-block
Except block
2019-05-04 18:49:23 +02:00
coolreader18
e91996b4e6 Merge pull request #896 from youknowone/pycomplex
PyComplex extend_class, uniform operand handling, missing methods + Complex64 IntoPyObject
2019-05-04 11:33:21 -05:00
coolreader18
406be20fe0 Merge pull request #914 from palaviv/wasm-import
Add browser.load_module
2019-05-04 10:32:07 -05:00
Aviv Palivoda
6c1dca7cc2 Add DirEntry.is_symlink 2019-05-04 18:14:21 +03:00
Aviv Palivoda
46ad1f5449 Add os.symlink 2019-05-04 18:01:23 +03:00
Aviv Palivoda
810b8ee4d0 Simplify PopException 2019-05-04 17:19:59 +03:00
Aviv Palivoda
32714f889e Remove empty params from ExceptHandler 2019-05-04 17:18:04 +03:00
Windel Bouwman
231343d63b Merge pull request #917 from palaviv/os-stat-2
Extend os.stat
2019-05-04 12:28:16 +02:00
Windel Bouwman
4a43872052 Merge pull request #903 from RustPython/lexer-error-improvements
Improve handling of lexical errors.
2019-05-04 11:56:33 +02:00
Aviv Palivoda
159063bb47 Convert windows file attributes to unix mode 2019-05-04 12:50:28 +03:00
Aviv Palivoda
d803acfdc5 Add yield in except test 2019-05-04 12:32:40 +03:00
Aviv Palivoda
5270da3934 Add ExceptHandler block 2019-05-04 12:32:40 +03:00
Aviv Palivoda
775be3a36a Add stat mode tests 2019-05-04 11:07:56 +03:00
Aviv Palivoda
b96f4a5758 Add CPython stat.py file 2019-05-04 11:00:36 +03:00
Aviv Palivoda
01b245f5df Add stat to DirEntry 2019-05-04 10:59:32 +03:00
jgirardet
5864c6e063 rewrite pybytearray with pybyteinner 2019-05-04 01:14:08 +02:00
Aviv Palivoda
c57fd1b96e Remove closure 2019-05-03 23:52:02 +03:00
Jeong YunWon
88e64adc56 Add complex __pow__ and __rpow__ 2019-05-04 01:05:27 +09:00
Jeong YunWon
930c8eef50 Add complex.{__mod__, __rmod__, __divmod__, __rdivmod__} 2019-05-04 01:05:27 +09:00
Jeong YunWon
9523baf5ac complex [r]truediv, [r]floordiv 2019-05-04 01:05:27 +09:00
Jeong YunWon
7c8880fb4a complex overflow message test 2019-05-04 01:05:27 +09:00
Jeong YunWon
2a2d0e4764 Add complex.__rmul__ 2019-05-04 01:05:27 +09:00
Jeong YunWon
982bbd69d8 complex.__bool__ uses Zero::is_zero instead of zero() 2019-05-04 01:05:27 +09:00
Jeong YunWon
61de5f2efc complex.__eq__ using try_float 2019-05-04 01:05:27 +09:00
Jeong YunWon
9a7fadcb6c Refactor PyComplex using try_complex 2019-05-04 00:59:19 +09:00
Jeong YunWon
7b438d9be8 impl IntoPyObject for Complex64 2019-05-04 00:59:19 +09:00
Jeong YunWon
9448254914 PyComplex uses extend_class for __new__ and __doc__ 2019-05-04 00:59:19 +09:00
Windel Bouwman
e578dcfc46 Merge pull request #899 from youknowone/float-complex
Add numbers.Complex impl to float + extend_class
2019-05-03 17:22:12 +02:00
Windel Bouwman
daf70424d2 Merge pull request #847 from jgirardet/kwargs
add other bytes method
2019-05-03 17:15:09 +02:00
Aviv Palivoda
d121b422b6 Add browser.load_module 2019-05-03 16:15:18 +03:00
Yonatan Goldschmidt
857a7014c2 Enable and extend strings/membership tests 2019-05-03 15:11:14 +03:00
Adam
1d6e8d5aa5 Merge pull request #905 from RustPython/mappingproxy
Mappingproxy
2019-05-03 09:58:37 +01:00
Windel Bouwman
199fce22be Merge pull request #900 from youknowone/int-pow
Fix int.__pow__
2019-05-03 07:30:16 +02:00
Y. Sapir
821959b889 Save REPL return value as _ 2019-05-03 03:10:03 +03:00
Y. Sapir
29ec26917f Return last expression in compile Mode::Single 2019-05-03 03:10:03 +03:00
Yonatan Goldschmidt
d1730a53ad Add basic string multiplication tests 2019-05-03 03:07:15 +03:00
Yonatan Goldschmidt
f12268f79a Implement str.__rmul__ 2019-05-03 03:07:15 +03:00
Yonatan Goldschmidt
a118497a4b Preallocate cloned strings with the minimum expected length
Similar to 620bea78.
2019-05-03 03:07:15 +03:00
coolreader18
18264b2881 Merge pull request #907 from Jongy/str-title-preallocate
Preallocate output string of str.title() with required size
2019-05-02 18:38:15 -05:00
Y. Sapir
6f66e8440d Add tests for return type of bool.__or__ etc. 2019-05-03 01:54:18 +03:00
Y. Sapir
ea347dfdec Implement bool.__or__, __and__ and __xor__ 2019-05-03 01:54:18 +03:00
Y. Sapir
26306b528f Simplify PyInt.rxor to reuse PyInt.xor 2019-05-03 01:42:17 +03:00
Yonatan Goldschmidt
620bea7830 Preallocate output string of str.title() with required size 2019-05-03 01:14:06 +03:00
Adam Kelly
65d602571d Create mappingproxy type with __getitem__ and __contains__. 2019-05-02 16:45:00 +01:00
Adam Kelly
dd0c70f289 Fix typo in objobject. 2019-05-02 16:36:35 +01:00
Windel Bouwman
b3b523ffa9 Add await syntax. 2019-05-02 17:11:51 +02:00
Windel Bouwman
5bc1aa08dc Add async def and async for parsing. 2019-05-02 16:55:33 +02:00
Jeong YunWon
0bf7ff96b8 Special handling for base -1, 0, 1 for big exp 2019-05-02 23:11:00 +09:00
Jeong YunWon
c18615b6e5 Fix __builtins__.pow to perform modpow for 3rd argument 2019-05-02 22:59:08 +09:00
Jeong YunWon
8d4562b0bb Fix __builtins__.pow to reflect __rpow__ 2019-05-02 22:59:06 +09:00
Jeong YunWon
eb9ca06ee7 Add int.__rpow__ 2019-05-02 22:59:05 +09:00
Jeong YunWon
614378d720 Add int.__pow__ negative exp impl 2019-05-02 22:44:28 +09:00
Jeong YunWon
c138dea992 Remove int.__pow__ float handling 2019-05-02 14:23:35 +09:00
coolreader18
8f3b62ba0e Merge pull request #895 from youknowone/pyrange-extend
extend_class for PyRange
2019-05-01 20:15:58 -05:00
coolreader18
3051702a2d Merge branch 'master' into pyrange-extend 2019-05-01 20:15:50 -05:00
coolreader18
fc729fd610 Merge pull request #892 from youknowone/float-round
Add basic float.__round__ without ndigits support
2019-05-01 20:07:02 -05:00
coolreader18
fa148a4aed Merge branch 'master' into float-round 2019-05-01 20:06:52 -05:00
coolreader18
3e7d43e27c Merge pull request #889 from adrian17/iter-class
Convert iterators to pyclass macros
2019-05-01 16:32:46 -05:00
Adrian Wielgosik
c7fd54e809 Convert iterators to pyclass macros 2019-05-01 21:26:37 +02:00
Windel Bouwman
1247a35be9 Improve handling of lexical errors. 2019-05-01 21:05:21 +02:00
Windel Bouwman
1f002e8df3 Merge pull request #887 from youknowone/to_int
objint::to_int to call __int__
2019-05-01 19:08:54 +02:00
Jeong YunWon
4a598d03e2 Add float.imag, float.conjugate 2019-05-01 21:31:02 +09:00
Jeong YunWon
bb878a3402 PyFloat to use extend_class for __new__ and __doc__ 2019-05-01 21:31:02 +09:00
Windel Bouwman
08b716f694 Merge pull request #898 from youknowone/builtins-divmod
Fix __builtins__.divmod to reflect __rdivmod__
2019-05-01 14:23:38 +02:00
Windel Bouwman
eb5cef20ba Merge pull request #897 from youknowone/test-utils
Temporary fix to assertRaises and assert_raises prints errors
2019-05-01 14:11:23 +02:00
Windel Bouwman
7358017671 Merge pull request #902 from lili668668/bytearray_append
Add bytearray.append
2019-05-01 14:10:17 +02:00
Tzu-Yin Hong
4ef65d8ac3 Add bytearray.append 2019-05-01 15:53:28 +08:00
Jeong YunWon
0d891cba2c Temporary fix to assertRaises and assert_raises prints errors 2019-05-01 12:07:01 +09:00
coolreader18
b542b39f5e Merge pull request #893 from youknowone/float-overflow
PyFloat overflow handling + missing methods
2019-04-30 21:36:27 -05:00
Jeong YunWon
14dd85a596 Fix __builtins__.divmod to reflect __rdivmod__ 2019-05-01 05:14:52 +09:00
Jeong YunWon
22a35c9b90 extend_class for PyRangeIterator 2019-05-01 05:13:05 +09:00
jgirardet
0d505adbb5 use PyBytinner as arg 2019-04-30 22:01:45 +02:00
Jeong YunWon
1c814ff2b5 Add float.__rpow__ 2019-05-01 04:02:34 +09:00
Jeong YunWon
09710b5222 Add float.__rdivmod__ and div/mod tests 2019-05-01 03:40:28 +09:00
Jimmy Girardet
fd614b7a75 refactor split options 2019-04-30 20:24:12 +02:00
Jimmy Girardet
cf70323475 add replace 2019-04-30 20:24:12 +02:00
Jimmy Girardet
b60d7413b9 add zfill 2019-04-30 20:24:12 +02:00
jgirardet
29f674fa1d fix split with empty bytes 2019-04-30 20:24:12 +02:00
jgirardet
d89ca3c3e4 add spitlines 2019-04-30 20:24:12 +02:00
jgirardet
434985d6d0 add partition/reparition refactor split/rsplit 2019-04-30 20:24:12 +02:00
jgirardet
0af8ad05eb add expandstab 2019-04-30 20:24:12 +02:00
jgirardet
cfff7cbd63 add split and rsplit 2019-04-30 20:24:12 +02:00
Jeong YunWon
813307f8f9 Refactor PyFloat using try_float() 2019-05-01 01:22:56 +09:00
Jeong YunWon
a0ad4368c6 Add float.pow OverflowError handling 2019-05-01 01:22:52 +09:00
Jeong YunWon
a318e4e09e objfloat.rs try_float for common operand handling 2019-05-01 01:21:14 +09:00
Jimmy Girardet
5d13daef20 remove all try_as_bytes_like 2019-04-30 18:01:40 +02:00
Jeong YunWon
599f1f678f extend_class for PyRange 2019-05-01 00:51:47 +09:00
jgirardet
ece6601851 add PyByteInner as fn argument / use Either 2019-04-30 15:47:41 +02:00
Windel Bouwman
177704f1ea Merge pull request #891 from ntrinquier/add-methods-for-numeric-types
Add methods for the complex type
2019-04-30 08:16:44 +02:00
Jeong YunWon
c951cb3cfd float.__round__ for ndigits == 0 2019-04-30 06:09:48 +09:00
Jeong YunWon
132d34fc67 Add range.__eq__ 2019-04-29 15:10:59 -05:00
coolreader18
9c4a0710f3 Merge pull request #880 from youknowone/fix-range-negative
Fix range() to support negative index + Add range.__eq__
2019-04-29 15:09:20 -05:00
Jeong YunWon
b7c7591639 Fix float.__trunc__ to handle abnormal values 2019-04-30 03:30:35 +09:00
Jeong YunWon
4c8f655d4e float.__round__ inf/nan support 2019-04-30 03:30:30 +09:00
Nicolas Trinquier
490db0a84f Add support for complex type for the to_complex function 2019-04-29 20:13:01 +02:00
Jeong YunWon
68e15a2bd8 Add basic float.__round__ without ndigits support 2019-04-30 03:11:31 +09:00
coolreader18
fd91d26444 Merge pull request #890 from palaviv/exc-stack
Add exceptions stack to VirtualMachine
2019-04-29 13:07:00 -05:00
Aviv Palivoda
56ef6ec5f8 Change to is_some 2019-04-29 20:08:15 +03:00
Nicolas Trinquier
eebdbfe679 Add int and float methods for the complex type 2019-04-29 18:39:10 +02:00
Nicolas Trinquier
f8373aa38a Add mul method for the complex type 2019-04-29 18:34:35 +02:00
Windel Bouwman
e3e2e7f905 Merge pull request #869 from skinny121/isinstance_tuple_arg
Accept a tuple for the second argument of isinstance and issubclass
2019-04-29 13:34:40 +02:00
Adam
63a71d6b50 Merge pull request #855 from RustPython/nonlocal-errors
Add check for nonlocal on top level.
2019-04-29 11:30:39 +01:00
ben
4a4631a622 Use match_class instead of Either in isinstance/issubclass 2019-04-29 19:41:42 +12:00
ben
81dd5faa81 Accept a tuple for the second argument of isinstance and issubclass 2019-04-29 19:41:42 +12:00
Windel Bouwman
2c7f3b5bb1 Merge pull request #888 from youknowone/math-rounding
Add trunc, ceil, floor to math module
2019-04-29 08:05:15 +02:00
coolreader18
9feeee059e Merge pull request #886 from youknowone/pycomplex
Add complex.__bool__, complex.__sub__, OverflowError/float support of complex.__add__
2019-04-28 18:44:21 -05:00
Jeong YunWon
388b62aae2 objint::to_int to call __int__ 2019-04-29 04:39:52 +09:00
Jeong YunWon
6afe78c9a6 Add math.ceil / math.floor 2019-04-29 04:26:10 +09:00
Jeong YunWon
c3714c2eca Add math.trunc 2019-04-29 04:26:10 +09:00
Windel Bouwman
53dea486d2 Merge pull request #878 from sanxiyn/fix-just
Fix justification
2019-04-28 19:13:33 +02:00
Windel Bouwman
bea6b48d1f Merge pull request #885 from youknowone/pyfloat
Add __int__, __float__, __trunc__, __rmod__ to float
2019-04-28 19:08:32 +02:00
Aviv Palivoda
b72fc3bc9d Add test for #867 2019-04-28 19:20:16 +03:00
Aviv Palivoda
af7a89aa99 pop exception on context 2019-04-28 19:06:14 +03:00
Aviv Palivoda
f1551af0f5 Add tests - not working 2019-04-28 18:52:52 +03:00
Jeong YunWon
20b2f64cef Add float.__rmod__ 2019-04-28 22:46:21 +09:00
Jeong YunWon
304cea89b8 objint::get_float_value 2019-04-28 20:31:07 +09:00
Jeong YunWon
8047ab3d3e Add float tests 2019-04-28 20:03:30 +09:00
Jeong YunWon
4810a55c82 Add float.__trunc__ 2019-04-28 12:44:25 +09:00
Jeong YunWon
9dda776e25 Add float.__int__ / float.__float__ 2019-04-28 12:41:59 +09:00
Jeong YunWon
dc05459459 Add float.__sub__, float.__rsub__ 2019-04-28 12:20:45 +09:00
Jeong YunWon
a2625916f5 Fix complex.__add__ to support float 2019-04-28 12:01:54 +09:00
Jeong YunWon
2eae737f3d complex.__add__ can raises OverflowError 2019-04-28 06:52:54 +09:00
Jeong YunWon
15e4e678ca Add complex.__bool__ 2019-04-28 06:19:12 +09:00
Jeong YunWon
ed79ccc6b1 PyComplex uses PyClassImpl 2019-04-28 06:04:21 +09:00
Jeong YunWon
7fb98c91d2 PyFloat uses #[pyclass] #[pyimpl] #[pymethod] 2019-04-28 05:47:29 +09:00
Windel Bouwman
88e52ef842 Merge pull request #884 from adrian17/imul
Support list.__imul__
2019-04-27 21:08:39 +02:00
Windel Bouwman
a2858cee7e Merge pull request #882 from youknowone/add-type-name
Add type.__name__
2019-04-27 21:07:17 +02:00
Aviv Palivoda
60afbb4bf5 Don't pop exeption for context 2019-04-27 21:53:08 +03:00
Jeong YunWon
d87468a1cb Add type.__name__ 2019-04-28 03:21:26 +09:00
Adrian Wielgosik
9d40a4c9d8 Support list.__imul__ 2019-04-27 17:44:21 +02:00
Agent
180ec22d4b Add constants to os module (#883) 2019-04-27 09:41:19 -05:00
Aviv Palivoda
4b9bafc824 Remove in_exc_handler for Raise 2019-04-27 14:33:24 +03:00
Aviv Palivoda
462c8233f3 Add exceptions stack to VirtualMachine 2019-04-27 14:21:01 +03:00
Jeong YunWon
a7091ca88d Add range.__eq__ 2019-04-27 00:54:21 +09:00
Jeong YunWon
16353f4f54 range negative side bound error 2019-04-27 00:13:54 +09:00
Jeong YunWon
16152a1d32 Fix range() to support negative index 2019-04-27 00:06:29 +09:00
Seo Sanghyeon
0e9acdc12b Fix justification 2019-04-26 15:33:37 +09:00
Agent
6e867edb6d Fix json.loads (#876)
* Fix json.loads
2019-04-25 23:17:16 -05:00
coolreader18
13a8bc1c11 Merge pull request #875 from sanxiyn/test-json-dict
Enable dict round trip test for json
2019-04-25 20:41:30 -05:00
coolreader18
1088f7061c Merge pull request #874 from RustPython/coolreader18/os-android
Add a cfg for os.stat for android
2019-04-25 17:59:24 -05:00
coolreader18
e4698987bb Add a cfg for os.stat for android 2019-04-25 16:59:06 -05:00
Seo Sanghyeon
e6f08cf93e Enable dict round trip test for json 2019-04-26 06:29:01 +09:00
Windel Bouwman
950344990a Merge pull request #872 from ypyf/master
Fix os_stat for MacOS
2019-04-25 20:37:45 +02:00
Windel Bouwman
3145d2a8fd Merge pull request #870 from RustPython/dict_fromkeys
Dict fromkeys
2019-04-25 20:35:57 +02:00
coolreader18
b30b446fe2 Merge pull request #871 from sanxiyn/strip-arg
Implement stripping with arguments
2019-04-25 09:17:13 -05:00
Yan Feng
d48b59fd74 Fix os_stat for MacOS 2019-04-25 20:13:04 +08:00
Seo Sanghyeon
f38f263d93 Implement stripping with arguments 2019-04-25 20:33:30 +09:00
Adam Kelly
d3f4c8f6e1 Use unwrap_or_else for OptionalArg in dictionary. 2019-04-25 09:07:17 +01:00
Adam Kelly
4f0b17e84f Add dict.fromkeys. 2019-04-25 09:07:17 +01:00
Adam Kelly
1a48fb17df Add PyContext.new_classmethod 2019-04-25 09:07:17 +01:00
Adam Kelly
cad4a13cf7 Add utility methods for default optional args. 2019-04-25 09:07:17 +01:00
Adam
6f04bebae5 Merge pull request #866 from RustPython/dict_popitem
dict.popitem & dict.setdefault
2019-04-25 09:06:28 +01:00
Adam Kelly
1c43a6bfbe Add dict.setdefault. 2019-04-25 08:04:54 +01:00
Adam Kelly
ceac014a6c Add dict.popitem. 2019-04-25 08:04:24 +01:00
Windel Bouwman
a8b2d1384c Merge pull request #865 from sanxiyn/test-comparison-error
Test error cases of comparisons
2019-04-25 07:18:02 +02:00
coolreader18
291e33af16 Merge pull request #868 from skinny121/rpartition_bug
Fix rpartition bug
2019-04-24 18:28:22 -05:00
ben
d84b8b52a5 Fix the tuple from rpartition being in wrong order when sub isn't
contained within the string
2019-04-25 10:37:59 +12:00
Windel Bouwman
8982f567b0 Add nonlocal binding check. 2019-04-24 15:19:52 +02:00
Seo Sanghyeon
fb62653c5c Test error cases of comparisons 2019-04-24 19:28:21 +09:00
Windel Bouwman
1081ea048a Merge pull request #864 from sanxiyn/test-integer-literal
Test integer literals
2019-04-24 09:28:15 +02:00
Windel Bouwman
86acb7aa3a Merge pull request #860 from palaviv/os-stat
Add os.stat
2019-04-24 09:27:21 +02:00
Windel Bouwman
2b2165f459 Merge pull request #861 from youknowone/main-py
Add __main__.py support
2019-04-24 09:21:32 +02:00
Seo Sanghyeon
f9124f41a8 Test integer literals 2019-04-24 04:00:52 +09:00
Jeong YunWon
29c0d89033 test_run_script for filr/dir 2019-04-24 02:38:26 +09:00
Jeong YunWon
2eb97aa1e8 Add __main__.py support 2019-04-23 20:27:25 +09:00
Windel Bouwman
7f8217472e Merge pull request #859 from youknowone/dict-pop
Add built-in dict.pop
2019-04-23 07:12:00 +02:00
Jeong YunWon
1d5adc4353 Add built-in dict.pop 2019-04-23 10:34:06 +09:00
Aviv Palivoda
55bd00b600 Add stat_result.{st_size} 2019-04-22 18:52:35 +03:00
Aviv Palivoda
56958552f4 Add stat_result.{st_nlink, st_uid, st_gid} 2019-04-22 18:47:10 +03:00
Aviv Palivoda
9a1caa08c3 Add stat_result.{st_ino, st_dev} 2019-04-22 18:35:38 +03:00
Aviv Palivoda
384bf5b545 Add os.stat 2019-04-22 18:27:39 +03:00
coolreader18
b9082b02e0 Merge pull request #858 from youknowone/fix-readme
Fix README not to refer moved file
2019-04-22 07:55:54 -05:00
Jeong YunWon
9f7676589f Fix README not to refer moved file
`cargo run tests/snippets/whats_left_to_implement.py`
-> `./whats_left.sh`
2019-04-22 21:31:22 +09:00
coolreader18
9e54dbef7c Merge pull request #856 from palaviv/socket-new-args
Convert socket to new args style
2019-04-21 19:00:37 -05:00
Aviv Palivoda
cb32201904 Add Address 2019-04-22 00:18:19 +03:00
Windel Bouwman
ce8ea805ae Add check for nonlocal on top level. 2019-04-21 19:40:14 +02:00
Windel Bouwman
adb66322c5 Merge pull request #852 from palaviv/scandir
Add os.scandir
2019-04-21 18:56:29 +02:00
coolreader18
d55d8841ad Merge pull request #854 from sanxiyn/delete-tuple
Implement deleting tuples
2019-04-21 11:47:46 -05:00
coolreader18
801c864645 Bump WASM npm version 2019-04-21 11:30:40 -05:00
Seo Sanghyeon
2aeb0ad59b Assert deleted variables are really deleted 2019-04-22 00:26:30 +09:00
coolreader18
0478358fd9 Merge pull request #853 from palaviv/set-disjoint
Add set.isdisjoint
2019-04-21 09:58:29 -05:00
Seo Sanghyeon
87f9a8e634 Implement deleting tuples 2019-04-21 23:48:13 +09:00
Aviv Palivoda
b61cd6f011 Simplify return values 2019-04-21 17:44:41 +03:00
Aviv Palivoda
1f73393255 Move more socket methods to new arg style 2019-04-21 17:35:20 +03:00
Aviv Palivoda
9954361df9 Move more socket methods to new arg style 2019-04-21 17:28:41 +03:00
Aviv Palivoda
206ba4dbfb Change socket to new args style 2019-04-21 17:20:33 +03:00
Aviv Palivoda
3986e2f87d Add set.isdisjoint 2019-04-21 16:41:36 +03:00
Aviv Palivoda
64e6ea0016 Add DirEntry.{is_file} 2019-04-21 12:06:49 +03:00
Aviv Palivoda
548f3f34c4 Add DirEntry.{is_dir} 2019-04-21 12:04:12 +03:00
Aviv Palivoda
858a6d03b0 Add DirEntry.{name, path} 2019-04-21 11:42:57 +03:00
Aviv Palivoda
3828652da6 Add os.scandir 2019-04-21 11:17:36 +03:00
Windel Bouwman
3afb5d39ed Merge pull request #850 from palaviv/socket-fileno
Socket.fileno
2019-04-20 14:36:05 +02:00
Joey
01f143ec7b Merge pull request #832 from RustPython/joey/proper-titlecase
str: proper titlecase support
2019-04-19 17:05:12 -07:00
coolreader18
de3900bcad Upgrade deps 2019-04-19 15:17:03 -05:00
Windel Bouwman
52a1a95ab0 Merge pull request #846 from LuoZijun/add-benches
Add benches
2019-04-19 22:15:08 +02:00
coolreader18
89aa07720d Merge pull request #851 from RustPython/coolreader18/pycallable
Add PyCallable
2019-04-19 13:34:33 -05:00
luozijun
7822f6d8d8 Add benches 2019-04-20 02:09:06 +08:00
coolreader18
148ef5cd09 Merge pull request #849 from palaviv/os-temp-dir
Use temp directory for os test
2019-04-19 12:39:53 -05:00
coolreader18
a984fd34d9 Update callable test 2019-04-19 12:11:18 -05:00
coolreader18
ac3cfca0fa Fix callable (again) 2019-04-19 12:04:22 -05:00
coolreader18
cf5e106748 Fix is_callable 2019-04-19 11:43:24 -05:00
Joey
ae8ea1d060 Merge remote-tracking branch 'origin/master' into joey/proper-titlecase 2019-04-19 09:27:00 -07:00
Joey
29ea307f4c unicode-casing: specify rev explicitly, add todo comment 2019-04-19 09:26:24 -07:00
coolreader18
a6f3b9a5ff Add PyCallable 2019-04-19 10:14:57 -05:00
coolreader18
2a74e48d98 Add vm.is_callable 2019-04-19 10:10:56 -05:00
Aviv Palivoda
d704a0fcda Rename os test folder 2019-04-19 17:14:14 +03:00
Aviv Palivoda
8215ec0a7c Don't delete test dir 2019-04-19 17:04:04 +03:00
Aviv Palivoda
f42c2a6ba5 Test fileno only on posix 2019-04-19 16:58:43 +03:00
Aviv Palivoda
aef973802c Close open reference to test file 2019-04-19 16:20:44 +03:00
Aviv Palivoda
2bc72dae9f Move fileno logic to Connection impl 2019-04-19 16:10:55 +03:00
Aviv Palivoda
e7b059ed9c Add socket.fileno for windows 2019-04-19 16:00:00 +03:00
Aviv Palivoda
cf0a920743 Add socket.fileno for unix 2019-04-19 15:50:06 +03:00
Aviv Palivoda
08f2a5705b Add prints for windows debug 2019-04-19 14:40:01 +03:00
Aviv Palivoda
00e46b7d72 Try to fix windows test 2019-04-19 13:50:34 +03:00
Aviv Palivoda
abb9cde62c Use temp dir for os test 2019-04-19 12:23:45 +03:00
Aviv Palivoda
a75e7635d5 Add os.sep 2019-04-19 12:09:11 +03:00
jgirardet
61ee15b97b add strip lstrip rstrip 2019-04-19 00:04:39 +02:00
jgirardet
9ea823abf1 add rfind, rindex 2019-04-18 23:06:11 +02:00
jgirardet
8a2ce9e260 add swapcase 2019-04-18 21:58:15 +02:00
jgirardet
a42bfae84d kwargs for translate 2019-04-18 21:41:46 +02:00
jgirardet
03997273ed refactor index/find with ByteInnerOptions 2019-04-18 21:12:45 +02:00
jgirardet
56c5790745 reformat center, ljsut, rjust args 2019-04-18 21:00:33 +02:00
jgirardet
1669d5280f refactor count 2019-04-18 20:41:12 +02:00
jgirardet
8bcdbbf21b use PyInt Ref, add ljust, rjust 2019-04-18 19:52:17 +02:00
coolreader18
19be5c9cf5 Merge pull request #845 from RustPython/coolreader18/proc-macro-span-errors
Target rustpython_derive errors at specific source spans
2019-04-18 12:30:24 -05:00
jgirardet
ba67f3c264 refactore fromhex 2019-04-18 19:25:45 +02:00
jgirardet
4a4d163626 refactor getitem 2019-04-18 19:10:37 +02:00
jgirardet
44d58f63ab refactor contains 2019-04-18 19:03:08 +02:00
jgirardet
473ae24199 use PyStringRef in new 2019-04-18 17:31:58 +02:00
jgirardet
84d61a9212 bytes.new with kwargs 2019-04-18 14:56:47 +02:00
jgirardet
046bd9b6d8 reactor bytes.center 2019-04-18 14:15:13 +02:00
jgirardet
8693adcd61 handle None case for bytes.translate 2019-04-18 14:15:13 +02:00
Jimmy Girardet
0b283102a6 add translate 2019-04-18 14:15:13 +02:00
Jimmy Girardet
ced6f15a59 add bytes.makertans 2019-04-18 14:15:13 +02:00
Jimmy Girardet
bd2166789d add bytes index and find 2019-04-18 14:15:13 +02:00
Jimmy Girardet
8a7c46da7b add endswith startswith 2019-04-18 14:15:13 +02:00
Jimmy Girardet
14658b6236 move is_byte to try_as_byte
move trait IsByte to ByteOr
refactor center
refactor count
fix center with negative value
add test for count(integer)
2019-04-18 14:15:13 +02:00
jgirardet
5f5d5c4278 add bytes.join 2019-04-18 14:15:13 +02:00
jgirardet
e6d6b77698 fix error msg 2019-04-18 14:15:13 +02:00
jgirardet
00cf524814 add slice capability to bytes. add trait IsByte 2019-04-18 14:15:13 +02:00
jgirardet
c550360be5 add is_bytes_like add bytes.count wthout slice 2019-04-18 14:15:13 +02:00
Windel Bouwman
319bb807fb Merge pull request #843 from jgirardet/parsenew
support bytes creation from hex and ascii
2019-04-18 08:35:45 +02:00
jgirardet
eb2d0b01ee refactor lex byte 2019-04-18 08:06:06 +02:00
Windel Bouwman
ae7058ffa8 Merge pull request #842 from RustPython/benchmarking
Add some benchmark scripts.
2019-04-18 07:05:25 +02:00
Windel Bouwman
6cf7f79dd4 Merge pull request #844 from RustPython/improve-syntax-error
Improve syntax error with line information.
2019-04-18 07:03:40 +02:00
coolreader18
48b0a17e4d Merge branch 'master' into coolreader18/proc-macro-span-errors 2019-04-17 20:45:50 -05:00
Windel Bouwman
b34784e9ef Format main.rs 2019-04-17 20:52:53 +02:00
Windel Bouwman
eb16f16566 Improve syntax error with line information. 2019-04-17 20:02:24 +02:00
Adam
615a121200 Merge pull request #841 from RustPython/mutual-import
Support mutual importing modules.
2019-04-17 15:09:23 +01:00
Jimmy Girardet
9c57ae4046 support bytes creation from hex and ascii 2019-04-17 15:28:14 +02:00
Windel Bouwman
84457e6e92 Add some benchmark scripts. 2019-04-17 15:04:50 +02:00
Windel Bouwman
2a8b586622 Fix caching of rust modules. 2019-04-17 14:03:18 +02:00
Windel Bouwman
240c1e42db Merge pull request #839 from RustPython/nonlocal
Add nonlocal support.
2019-04-17 14:02:04 +02:00
Windel Bouwman
6d1b807c77 Improve error message of unwrap operation on nonlocal scope. 2019-04-17 12:59:56 +02:00
Windel Bouwman
06563a36f6 Support mutual importing modules. 2019-04-17 12:33:09 +02:00
Windel Bouwman
75e8f81e77 Merge pull request #767 from skinny121/slice_new
Refactor slice.__new__ to new style function
2019-04-17 12:11:04 +02:00
Windel Bouwman
780ee8a767 Merge pull request #840 from RustPython/coolreader18/fix-unsetenv-test
Fix os.unsetenv test for windows
2019-04-17 12:08:02 +02:00
ben
9b71424d4e Use slice.xxx_index() methods in setslice and delslice 2019-04-17 20:02:08 +12:00
ben
f2873a519d Merge branch 'master' into slice_new
# Conflicts:
#	tests/snippets/builtin_slice.py
#	vm/src/frame.rs
#	vm/src/obj/objrange.rs
#	vm/src/obj/objslice.rs
2019-04-17 19:44:46 +12:00
coolreader18
11bf84e8c1 Fix test again 2019-04-16 22:01:09 -05:00
coolreader18
96d6c518e9 Fix os.unsetenv test for windows 2019-04-16 19:40:01 -05:00
Windel Bouwman
6abf1511e9 Add nonlocal support. 2019-04-16 17:19:57 +02:00
coolreader18
d7275c7712 Merge pull request #837 from skinny121/main_rs_cleanup
Use new_syntax_error in main.rs
2019-04-16 06:58:18 -05:00
coolreader18
827f830d09 Merge pull request #836 from RustPython/coolreader18/no-proc-macro-hack
Remove the __inside_vm hack for procedural macros
2019-04-16 06:51:44 -05:00
ben
224863583b Use new_syntax error in main.rs 2019-04-16 20:53:14 +12:00
coolreader18
dc63fc8ce7 Switch to span-based errors for pyclass and pyimpl 2019-04-15 22:15:20 -05:00
coolreader18
08babef619 Remove the __inside_vm hack for procedural macros 2019-04-15 20:24:16 -05:00
Windel Bouwman
78db5ea311 Merge pull request #835 from RustPython/coolreader18/weakproxy
Add weakproxy
2019-04-15 17:35:04 +02:00
Adam
2c3f4b6de4 Merge pull request #816 from RustPython/dict_changed_during_iteration
Guard for changes in dictionary size during iteration.
2019-04-15 15:53:37 +01:00
Adam Kelly
dfbaf3cdf0 Remove pub from PyDict.entries (easy TODO) 2019-04-15 13:25:04 +01:00
Adam Kelly
c9b479c43b Guard for changes in dictionary size during iteration. 2019-04-15 13:25:04 +01:00
coolreader18
1612c954a1 Add weakproxy test 2019-04-14 20:14:54 -05:00
coolreader18
cc76bf7a1f Add weakproxy class 2019-04-14 20:09:43 -05:00
coolreader18
5855baf4ec Merge pull request #834 from dkaste/rust-2018-macros
Make macros comply fully with Rust 2018
2019-04-14 17:06:45 -05:00
Darren Kaste
a8e064b1c0 Import TypeProtocol before use in type_check! 2019-04-14 17:19:44 -04:00
Darren Kaste
daaeb78831 Prefix helper macro calls with $crate 2019-04-14 17:08:35 -04:00
Joey
79623f4e7a str: proper titlecase support 2019-04-14 12:23:09 -07:00
coolreader18
143e329f79 Merge pull request #831 from palaviv/exception-context
Exception reraise and context
2019-04-14 13:31:10 -05:00
Aviv Palivoda
2ffd1c9484 Fix typo 2019-04-14 20:39:28 +03:00
Aviv Palivoda
4068a36ce8 Use assertRaises 2019-04-14 20:38:34 +03:00
Aviv Palivoda
b6ce407391 Remove else and finally from in_exc_handler 2019-04-14 19:06:21 +03:00
Aviv Palivoda
aec7f84960 Print exception context 2019-04-14 18:55:29 +03:00
Aviv Palivoda
188758929d Add more tests to exception context 2019-04-14 18:54:43 +03:00
Aviv Palivoda
3ec9b01928 Add exception __context__ 2019-04-14 18:54:43 +03:00
Aviv Palivoda
2c2925a684 Support reraise 2019-04-14 18:54:43 +03:00
Windel Bouwman
51aa817a81 Merge pull request #829 from skinny121/unittest_rustpython
RustPython changes for #824
2019-04-14 10:49:21 +02:00
Windel Bouwman
71b6e2abf0 Merge pull request #806 from RustPython/symbol-table
Initial version of symbol table builder.
2019-04-14 10:44:43 +02:00
ben
307689a15e comment out lines that reference mappingproxy as type doesn't yet have a
__dict__
2019-04-14 19:10:10 +12:00
coolreader18
8f3319e01d Merge pull request #827 from RustPython/joey/titlecase
str: improve {is,}title impl and add tests
2019-04-13 22:59:04 -04:00
Joey
762c281dd4 address feedback 2019-04-13 19:07:15 -07:00
ben
a708ce2eb2 Remove needless format! 2019-04-14 12:15:55 +12:00
ben
d24dd170e9 Changes to RustPython to support importing and running unittest 2019-04-14 12:09:54 +12:00
coolreader18
c0d328ad18 Merge pull request #828 from skinny121/rust_1_34_update
Update code format and fix some clippy warnings
2019-04-13 19:20:06 -04:00
ben
6650ad895a Fix a bunch of clippy warnings 2019-04-14 10:07:50 +12:00
ben
1f8181b561 Update formatting to be consistent with rustfmt included in 1.34 2019-04-14 09:40:59 +12:00
Joey
8839461028 str: improve {is,}title impl and add tests 2019-04-13 12:45:09 -07:00
coolreader18
56765681f8 Merge pull request #826 from RustPython/joey/fix-compile
Fix sub-crate compilation
2019-04-13 14:21:26 -05:00
Joey
16644daffa Fix sub-crate compilation 2019-04-13 12:04:37 -07:00
Windel Bouwman
733d3a1d1f Merge master branch 2019-04-13 12:51:55 +02:00
Windel Bouwman
be4e3170af Merge pull request #822 from jgirardet/addbytesm
add capitalize bytes.center + fix str.center
2019-04-13 12:41:35 +02:00
Windel Bouwman
83ea419c63 Add load and store of global to name protocol. 2019-04-13 11:55:10 +02:00
Adam
78ab68a64e Merge pull request #817 from skinny121/function_metadata
Add __name__, __qualname__ and __module__ to functions and classes
2019-04-13 09:44:33 +01:00
jgirardet
73dbcfbe01 Add bytes.center
fix str.center
add some tests
introduce is_byte
2019-04-13 08:23:40 +02:00
jgirardet
bd78f7e12b add capitalize 2019-04-13 08:21:37 +02:00
coolreader18
2c887905a1 Merge pull request #766 from jgirardet/seq
Fix #746: invalid slice with start or stop =-1 when step<0
2019-04-12 16:41:36 -05:00
coolreader18
22203975fa Merge pull request #821 from palaviv/excpetion-cause
Add exception cause
2019-04-12 16:08:54 -05:00
Aviv Palivoda
256abe63b6 Use vm.new_type_error 2019-04-12 23:08:26 +03:00
Aviv Palivoda
20e0cc8bd7 Use assertRaises 2019-04-12 23:06:53 +03:00
coolreader18
a91cfd16bf Fix WASM import error 2019-04-12 14:28:26 -04:00
coolreader18
774b0d8e45 Merge pull request #823 from adrian17/remove-impl
Drop IntoPyNativeFunc impl to fix Nightly/Beta breakages.
2019-04-12 13:27:06 -05:00
Windel Bouwman
76659fd985 Merge pull request #820 from skinny121/gen_throw
Implement generator.throw
2019-04-12 19:38:54 +02:00
Windel Bouwman
456c8a19ce Merge pull request #819 from palaviv/os-env
Add os.environ
2019-04-12 19:33:33 +02:00
Adrian Wielgosik
585e6e5428 Drop IntoPyNativeFunc impl to fix Nightly/Beta breakages. 2019-04-12 19:28:09 +02:00
Windel Bouwman
76c597f2af Add global bytecode and testcase. 2019-04-12 19:24:23 +02:00
Adam
785854ac9e Merge pull request #818 from RustPython/dir_str_bug
Fix dir bug - not including object attributes correctly.
2019-04-12 15:26:49 +01:00
Aviv Palivoda
908f758cbe Print cause on exception 2019-04-12 15:50:17 +03:00
Adam Kelly
80ec464d84 Use dict.update to combine class and object attrs in object_dir. 2019-04-12 12:25:19 +01:00
ben
63643e1fdb Implement generator.throw 2019-04-12 20:30:37 +12:00
Aviv Palivoda
6c4b092641 Support exception __cause__ 2019-04-12 10:50:45 +03:00
Windel Bouwman
28cf4c0010 Symbol role scan fully covered. 2019-04-11 22:18:29 +02:00
Aviv Palivoda
b293956258 Use original _Environ as much as possible 2019-04-11 19:15:37 +03:00
Aviv Palivoda
1272829793 Comment unsupported code from _collections_abc.py 2019-04-11 19:03:08 +03:00
Aviv Palivoda
eb40e08d8a Add _collections_abc.py from CPython 2019-04-11 19:02:04 +03:00
Aviv Palivoda
69e49e6cba Simplify os.py 2019-04-11 18:55:53 +03:00
Aviv Palivoda
4293b11429 Add environ class 2019-04-11 18:55:53 +03:00
Aviv Palivoda
c33593efa9 Remove getenv and add environ 2019-04-11 18:55:53 +03:00
Aviv Palivoda
951659a54d Add os.unsetenv 2019-04-11 18:55:53 +03:00
Aviv Palivoda
9b475a2c41 Add os.putenv 2019-04-11 18:55:53 +03:00
Aviv Palivoda
72467069be Add os.getenv 2019-04-11 18:55:53 +03:00
Adam
42a3b7a75c Merge pull request #815 from RustPython/refactor_ast
Refactor ast.
2019-04-11 16:43:19 +01:00
Adam Kelly
8569145751 Define classes for all the ast types. 2019-04-11 16:41:47 +01:00
Adam Kelly
8a14665575 Ast refactor: Everything can fail. 2019-04-11 16:41:44 +01:00
Adam Kelly
d7e0ceec12 New (PyRef<T>) style types. 2019-04-11 16:40:54 +01:00
Adam Kelly
aa38a1aa51 Start refactor of ast. 2019-04-11 16:40:49 +01:00
Adam Kelly
664554bc5e Fix dir bug - not including object attributes correctly. 2019-04-11 15:35:01 +01:00
Windel Bouwman
7cf3135878 Merge pull request #812 from RustPython/dict_eq
Dict eq
2019-04-11 13:33:18 +02:00
ben
2164cb5e65 Produce correct value for __qualname__ and add attributes to class. 2019-04-11 20:13:23 +12:00
ben
84eff4a7ac Add __name__ and __module__ to functions 2019-04-11 20:13:23 +12:00
Adam Kelly
b70f989952 dict equality - objects always equal themselves. 2019-04-11 08:39:03 +01:00
Adam Kelly
bd5772d914 Implement dict.__eq__ 2019-04-11 08:31:13 +01:00
Adam Kelly
939f109375 Merge branch 'dict_into_iter' 2019-04-11 08:29:13 +01:00
Adam Kelly
aeb84936ff Merge branch 'master' into dict_into_iter 2019-04-11 08:28:12 +01:00
Windel Bouwman
58a393f047 Merge pull request #804 from jgirardet/refactore_bytes
refactor bytes
2019-04-11 08:20:01 +02:00
coolreader18
ef55efb631 Merge pull request #814 from RustPython/coolreader18/pyproperty-attr
Change #[pymethod(property)] to #[pyproperty]
2019-04-10 22:19:00 -05:00
coolreader18
6a190e39f3 Fix __radd__ and __rmul__ 2019-04-10 20:41:06 -05:00
coolreader18
dd4539b1a6 Change to use PyClassImpl::extend_class 2019-04-10 18:02:30 -05:00
coolreader18
c5f4eab142 Change objint to impl style with properties 2019-04-10 17:55:24 -05:00
coolreader18
2bdaa02700 Improve error messages 2019-04-10 17:45:07 -05:00
coolreader18
d099165e3b Rename item_name -> item_ident 2019-04-10 17:41:45 -05:00
coolreader18
47bd9680f9 Change ClassItem to enum 2019-04-10 17:41:25 -05:00
jgirardet
9d25a216de fix some tests, run clippy 2019-04-10 21:39:16 +02:00
Jimmy Girardet
54c7335f1c SyntaxError for non ascii char 2019-04-10 18:05:28 +02:00
jgirardet
751c3d52e2 use vec! for int arg in bytes new 2019-04-10 13:24:31 +02:00
Adam Kelly
e04275b199 Missed get_key_values_pairs removal in wasm. 2019-04-10 09:48:53 +01:00
Adam Kelly
8f840d5376 Pick code review nits. 2019-04-10 09:28:54 +01:00
Adam Kelly
9a92159413 Remove unneeded Cell on DictIter. 2019-04-10 09:26:03 +01:00
Jimmy Girardet
977f56ade1 add bytes.fromhex 2019-04-10 10:08:10 +02:00
coolreader18
cbdab226d9 Change #[pymethod(property)] to #[pyproperty] 2019-04-09 22:07:21 -05:00
Jimmy Girardet
5cc83a35aa hex 2019-04-09 17:08:38 +02:00
Jimmy Girardet
9b763072fe add upper lower 2019-04-09 16:23:56 +02:00
Adam
d84ad431e1 Merge pull request #811 from RustPython/dict_view_len
Add __len__ to dictionary views.
2019-04-09 14:09:49 +01:00
Jimmy Girardet
6c745f68dd fix typo, fix bytesinner.add now return Vec[u8] 2019-04-09 14:43:13 +02:00
Jimmy Girardet
2940c7cc28 add islpaha isalnum isdigit islower isupper isspace istitle 2019-04-09 14:33:29 +02:00
Adam Kelly
ec5fd550de Implement IntoIterator for PyDictRef. 2019-04-09 11:30:52 +01:00
Adam Kelly
25d3f83e4d Add __len__ to dictionary views. 2019-04-09 11:28:25 +01:00
Adam
31fd2936c5 Merge pull request #796 from RustPython/dict_iters
Dict iters
2019-04-09 11:11:14 +01:00
Adam Kelly
f3f3d8a478 Merge branch 'Ryex-ryex-list.__delitem__slice_error' 2019-04-09 10:31:55 +01:00
Adam
39042e6475 Merge pull request #805 from Ryex/ryex-list.__setitem__
implement  list.__setitem__ with slice and int indexing
2019-04-09 10:24:48 +01:00
Adam
958a0a2600 Merge pull request #809 from skinny121/dict_test_cleanup
Cleanup dict test snippet
2019-04-09 10:19:32 +01:00
Adam Kelly
d9216c87f1 Remove done todo. 2019-04-09 10:17:17 +01:00
Adam Kelly
23a4b1e9d8 Additional tests for dictionary iteration. 2019-04-09 10:13:44 +01:00
ben
046e4b3fe3 Cleanup dict test snippet 2019-04-09 20:43:59 +12:00
Windel Bouwman
981c14fb0d Merge pull request #795 from RustPython/coolreader18/wasm-cleanup1
[WASM] Clean up a bit
2019-04-09 07:46:24 +02:00
coolreader18
422ab69b99 Use impl style classes 2019-04-08 21:50:38 -05:00
coolreader18
c581852b5b Merge branch 'master' into coolreader18/wasm-cleanup1 2019-04-08 21:49:04 -05:00
coolreader18
1568637d26 Merge branch 'master' into coolreader18/wasm-cleanup1 2019-04-08 21:41:45 -05:00
Rachel Powers
1101b6571c fix error related to #746 but for list.__delitem__ 2019-04-08 16:17:57 -06:00
Rachel Powers
b2a1f6580b fix error when start or stop of slice is -1 and step != 1 2019-04-08 15:56:06 -06:00
jgirardet
b535958310 add getitem, fix contain error_message 2019-04-08 23:12:40 +02:00
Rachel Powers
4d53ddedb0 test for if iter raises error 2019-04-08 14:45:34 -06:00
Windel Bouwman
8e07719e81 Merge branch 'master' of github.com:RustPython/RustPython into symbol-table 2019-04-08 22:32:00 +02:00
Rachel Powers
4c50defa37 extend PyIterable::try_from_object to work with sequences 2019-04-08 13:46:23 -06:00
jgirardet
8232a4d285 finish contains 2019-04-08 21:27:44 +02:00
Rachel Powers
d0e6d2fa32 add tests for custom iters 2019-04-08 13:18:37 -06:00
Rachel Powers
4e277cfcc2 move to useing PyIterable 2019-04-08 12:41:28 -06:00
coolreader18
e7e126e31d Fix whats_left.sh 2019-04-08 12:30:53 -05:00
Windel Bouwman
21e890daa4 Merge pull request #802 from andrew-ld/master
use a code generator for not implemented tests
2019-04-08 17:05:52 +02:00
Windel Bouwman
b1a95f669f Initial version of symbol table builder. 2019-04-08 17:02:27 +02:00
andrew
3aa110a296 add .gitignore 2019-04-08 16:03:35 +02:00
andrew
2811f27bb5 add a warning 2019-04-08 16:03:24 +02:00
Adam Kelly
29e9753e51 Even newer style class definitions. 2019-04-08 15:02:04 +01:00
Adam Kelly
2d127b9834 Use macro to generate full set of views and iterators. 2019-04-08 12:11:59 +01:00
Adam Kelly
5c4755ffd7 Separate iterators for items/keys/values. 2019-04-08 11:08:45 +01:00
Adam Kelly
9c32de954b Add iterator for dictionary keys. 2019-04-08 10:35:09 +01:00
Jimmy Girardet
86928114fa resolve conflict 2019-04-08 10:33:56 +02:00
jgirardet
c487f12222 Merge branch 'master' into seq 2019-04-08 09:36:37 +02:00
Jimmy Girardet
0e264426c9 fix import 2019-04-08 09:12:22 +02:00
Rachel Powers
a23b5bc470 cleanup and cargo fmt 2019-04-07 19:32:11 -06:00
Joey
7910c95ff0 Merge pull request #785 from palaviv/set-inner
refactor objset using inner
2019-04-07 18:20:37 -07:00
Rachel Powers
118c98ccc7 exhaustive (hopefully) test snippets
I attempted to cover every case with the snippets
 but I easily could of missed some.
2019-04-07 19:12:03 -06:00
Rachel Powers
4d8a56aea1 list.__setitem__ with slice and int indexing
optimisation is uncertain
correctness is uncertain

but it does appear to work
2019-04-07 19:09:44 -06:00
jgirardet
ec65b8480f add contains 2019-04-08 00:45:53 +02:00
jgirardet
3c736c1f94 iter 2019-04-08 00:11:20 +02:00
Aviv Palivoda
abc72e9992 contains return bool 2019-04-07 23:54:42 +03:00
jgirardet
dddf9fee39 gt lt ge le 2019-04-07 22:42:47 +02:00
jgirardet
ec98b4d6bf repr len eq 2019-04-07 22:36:13 +02:00
Aviv Palivoda
5ae921dc57 update function support iterable 2019-04-07 23:26:59 +03:00
Aviv Palivoda
848350d334 ior support only set and frozenset 2019-04-07 23:06:42 +03:00
Aviv Palivoda
3ed8727ee5 symmetric_difference support iterable 2019-04-07 23:01:49 +03:00
coolreader18
53aa57dbbe Merge pull request #803 from RustPython/joey/self-by-ref
int, str, range: take self by shared reference
2019-04-07 14:54:08 -05:00
Aviv Palivoda
e011e3f327 intersection and difference support iterable 2019-04-07 22:36:56 +03:00
Aviv Palivoda
fa369ff779 Limit non-operator versions to set and frozenset 2019-04-07 22:09:37 +03:00
Joey Hain
c2e03ed342 fix int.__float__ 2019-04-07 11:56:59 -07:00
jgirardet
f538a92007 pybytes.__new__ ok 2019-04-07 20:34:27 +02:00
Aviv Palivoda
3bc1e3598c Use PyIterable 2019-04-07 21:26:20 +03:00
Joey Hain
ea61599da4 range: take self by ref 2019-04-07 10:07:36 -07:00
Joey Hain
e70f174eb6 str: take self by ref 2019-04-07 10:07:36 -07:00
Joey Hain
aec33634ca int: take self by ref 2019-04-07 10:07:31 -07:00
Aviv Palivoda
a0aa88d2fb clear return implicit None 2019-04-07 20:02:27 +03:00
jgirardet
2eb8e7bf2b new ok for pybytes 2019-04-07 18:55:35 +02:00
Windel Bouwman
48cca16dd7 Merge pull request #801 from skinny121/dict_copy_update
Implement copy and update dict methods
2019-04-07 12:24:51 +02:00
andrew
f03a164c14 use a code generator for not implemented tests 2019-04-07 12:22:10 +02:00
Windel Bouwman
f4964dafbf Merge pull request #798 from skinny121/keyword_only_args
Implement keyword only argument defaults
2019-04-07 12:11:15 +02:00
Adam
90ded15339 Merge pull request #799 from RustPython/joey/ref-receiver
Allow first argument to be a shared ref to a python value
2019-04-07 10:02:03 +01:00
Adam
8a5d6ca79e Merge pull request #800 from skinny121/warning_classes
Add builtin warning classes
2019-04-07 09:51:23 +01:00
jgirardet
7e965c7cc8 check encoding in new 2019-04-07 10:12:57 +02:00
ben
32051c9d96 Implement copy and update dict methods 2019-04-07 19:19:39 +12:00
ben
02a21cd072 Add builtin warning classes 2019-04-07 17:42:10 +12:00
coolreader18
7ca3b77fcd Just a fn 2019-04-06 23:55:30 -05:00
coolreader18
5afc558564 Add id() method 2019-04-06 23:47:01 -05:00
Joey Hain
c2716040d2 float: take self by shared ref 2019-04-06 19:05:18 -07:00
Joey Hain
be55562457 Allow first argument to be a shared ref to a python value 2019-04-06 18:50:40 -07:00
jgirardet
10cbf2ae74 bytes._new stuff 2019-04-07 01:49:16 +02:00
ben
51732feaed Use get_item_option from ItemProtocol instead of get_item 2019-04-07 07:43:29 +12:00
ben
d5a9d96d62 Expose function.__defaults__ and function.__kwdefaults__(only getters) 2019-04-07 07:38:42 +12:00
ben
5fd3cf2bcd Implemented keyword only defaults 2019-04-07 07:38:42 +12:00
Windel Bouwman
d64554dab2 Merge pull request #797 from palaviv/os-dirs
Add os.{mkdir, mkdirs, rmdir, listdir}
2019-04-06 20:25:00 +02:00
Windel Bouwman
ea95fb2b4e Merge pull request #794 from RustPython/generic_dict
Parameterise dictdatatype::Dict by value type.
2019-04-06 20:18:22 +02:00
Aviv Palivoda
401ca08b65 Use map_err 2019-04-06 21:11:58 +03:00
Aviv Palivoda
a21aa6eac9 Add os.listdir 2019-04-06 19:14:23 +03:00
Aviv Palivoda
bf6b12266a Add os.rmdir 2019-04-06 18:30:40 +03:00
Aviv Palivoda
2ec6afeb11 Add os.mkdirs 2019-04-06 18:24:06 +03:00
Aviv Palivoda
eb9378fe90 Add os.mkdir 2019-04-06 18:20:18 +03:00
coolreader18
3aeaa05f1a Merge branch 'master' into coolreader18/wasm-cleanup1 2019-04-06 10:11:07 -05:00
Adam Kelly
e67d5f3c62 Parameterise dictdatatype::Dict by value type. 2019-04-06 16:06:42 +01:00
Windel Bouwman
d577bb7ac9 Merge pull request #787 from palaviv/os-fd
Add os.{read,write,remove,unlink}
2019-04-06 17:02:31 +02:00
Windel Bouwman
1faa7fa202 Merge pull request #783 from Ryex/ryex-impl-list.__delitem__
Implement list.__delitem__
2019-04-06 16:56:21 +02:00
Windel Bouwman
0f6a25c38e Merge pull request #791 from RustPython/dict_protocols
Dict protocols
2019-04-06 16:48:30 +02:00
Windel Bouwman
a6858befbc Merge pull request #792 from RustPython/docstring-fix
Fix moment when docstring is set.
2019-04-06 16:39:33 +02:00
Aviv Palivoda
04acfe2665 Remove failing line in windows 2019-04-06 17:29:52 +03:00
Aviv Palivoda
1f0fd39722 Change os new funcs to new arg style 2019-04-06 17:29:40 +03:00
Windel Bouwman
bcf94ed8bf Merge pull request #788 from RustPython/syntax-enhancements
Fix syntax for float literals, statements seperated by semicolons and…
2019-04-06 12:31:53 +02:00
Windel Bouwman
afb28bfccb Fix moment when docstring is set. 2019-04-06 11:53:59 +02:00
Adam Kelly
584b707356 Add dict.__missing__ support. 2019-04-06 10:15:34 +01:00
Adam Kelly
b1dd5836af Simpler implementation of ItemProtocol for PyDictRef. 2019-04-06 10:15:34 +01:00
Adam Kelly
e2a4f22be8 Avoid name similarity between ItemProtocol and inner methods. 2019-04-06 10:15:33 +01:00
Adam Kelly
0fe3f7748c Simplify PyDictRef.__repr__. 2019-04-06 10:15:31 +01:00
Adam Kelly
7b2d92f495 Delete DictProtocol. impl ItemProtocol for PyDictRef. 2019-04-06 10:15:29 +01:00
Adam Kelly
ee9066a713 dict.get shouldn't call into __getitem__ 2019-04-06 10:12:16 +01:00
Adam Kelly
3e42edd261 dict.__new__ - support for dict subtypes. 2019-04-06 10:12:16 +01:00
Windel Bouwman
42bb3465c3 Merge pull request #790 from skinny121/decorator_and_defaults
Fix decorator on functions with defaults
2019-04-06 11:08:01 +02:00
Windel Bouwman
b90a1cf6ef Merge pull request #789 from skinny121/dict_literal_order
Fix order of dict literal
2019-04-06 11:07:22 +02:00
coolreader18
157204c61a Clean up the wasm crate 2019-04-05 23:24:26 -05:00
Rachel Powers
909d94ec23 impl and use SequenceIndex for list.__delitem__
- removal of del_item
- all del function impl on PyListRef
- stepped deletion now loops only over the range
  insted of the whole list
2019-04-05 20:25:53 -06:00
ben
7fffc57255 Fix decorator on functions with defaults 2019-04-06 12:46:48 +13:00
jgirardet
a7d5b0e9ac start 2019-04-06 01:44:00 +02:00
Rachel Powers
c3ecf0ef9e Merge branch 'master' into ryex-impl-list.__delitem__ 2019-04-05 17:15:32 -06:00
ben
dda0d561ac Fix order of dict literal 2019-04-06 10:43:39 +13:00
Windel Bouwman
ab3d004c42 Fix syntax for float literals, statements seperated by semicolons and starargs after keyword arguments. 2019-04-05 21:59:20 +02:00
Windel Bouwman
8535ba9a56 Merge pull request #786 from RustPython/dict_cleanup
Dict cleanup
2019-04-05 20:56:58 +02:00
Aviv Palivoda
2a3a88c2f2 Use match_class macro to avoid unwanted clones 2019-04-05 19:59:01 +03:00
Aviv Palivoda
a685216f29 Use new arg style for set and frozenset new 2019-04-05 19:59:01 +03:00
Aviv Palivoda
ed8c1e1a95 Implement set and frozenset with PySetInner 2019-04-05 19:58:17 +03:00
Aviv Palivoda
cdd39bc50e Add tests for os.{read, write} 2019-04-05 19:51:38 +03:00
Aviv Palivoda
1f19951ece Add os.{remove,unlink} 2019-04-05 19:51:38 +03:00
Aviv Palivoda
28c3ef1ae3 Add os.write 2019-04-05 19:50:24 +03:00
Aviv Palivoda
37e7972dcd Add os.read 2019-04-05 19:49:13 +03:00
Adam Kelly
f354f4ce02 Move contains_key to PyDictRef. 2019-04-05 16:18:10 +01:00
Adam Kelly
0dce9bb96a Use item protocol when executing instructions. 2019-04-05 16:16:55 +01:00
Adam Kelly
4212594c5b Prefer key to needle. 2019-04-05 16:16:55 +01:00
Adam Kelly
ec94168a15 Remove objdict::get_key_value_pairs. 2019-04-05 16:16:55 +01:00
Windel Bouwman
59d8612cfa Merge pull request #782 from skinny121/abc_module
Add abc module from CPython
2019-04-05 17:05:45 +02:00
Windel Bouwman
e2293ead70 Merge pull request #780 from RustPython/dict_non_str_keys
Support non-string keys in dictionaries.
2019-04-05 16:56:58 +02:00
coolreader18
916066924e Merge pull request #784 from RustPython/joey/range-index
Add and use a RangeIndex type instead of Either
2019-04-05 09:05:14 -05:00
Adam Kelly
77d5f57df1 Add some additional dictionary tests. 2019-04-05 14:36:19 +01:00
Rachel Powers
a41e8973bd Merge branch 'master' into ryex-impl-list.__delitem__ 2019-04-05 03:59:44 -06:00
Adam Kelly
43347e2d8b Dictionary: KeyError -> ValueError. 2019-04-05 09:50:31 +01:00
Adam Kelly
b943f4a4bb Historic real proper dictionary support. 2019-04-05 09:50:31 +01:00
Adam Kelly
9ed051e3b7 Module Initialisation takes VirtualMachine rather than PyContext. 2019-04-05 09:50:31 +01:00
Adam Kelly
7438b0685c Changes suggested by code review. 2019-04-05 09:50:31 +01:00
Adam Kelly
c8eda3733d Eliminate ctx.set_attr. 2019-04-05 09:50:31 +01:00
Adam Kelly
25c17b4829 Change all the ctx.set_attr in ast. 2019-04-05 09:50:31 +01:00
Adam Kelly
f840bdcd7f Generalise set_attr. 2019-04-05 09:39:59 +01:00
Adam Kelly
bce4f1e483 Simplify/shrink the dict interface. 2019-04-05 09:39:59 +01:00
ben
79caaa5a0b Move PSF-LICENSE and add Lib README.md 2019-04-05 19:19:55 +13:00
jgirardet
d96a5b11f7 add resources to snippets 2019-04-04 21:32:04 +02:00
Windel Bouwman
95cbb530d8 Merge pull request #779 from RustPython/syntax-enhancements
Improve trailing comma situation
2019-04-04 19:45:28 +02:00
Joey
05ede30c51 range index 2019-04-04 07:52:53 -07:00
Joey
1c958c93b1 Merge pull request #774 from RustPython/joey/match-class
Add match_class! macro
2019-04-04 07:13:31 -07:00
Rachel Powers
d0e6c3bd92 convert to PySliceRef as it is the only option 2019-04-04 04:52:33 -06:00
Rachel Powers
e3994010f3 add list.__delitem__ test snippits 2019-04-04 04:04:26 -06:00
Rachel Powers
c97f342ef7 cleanup and rustfmt 2019-04-04 03:18:58 -06:00
Rachel Powers
aba059b81a impl PySliceableSequenceMut & objseqence::del_item
used to impl list.__delitem__
2019-04-04 02:52:51 -06:00
ben
c01dc5310a Add callback parameter to weakref, at the moment this callback isn't yet
implement though.
2019-04-04 20:11:53 +13:00
ben
ea872521d6 Make object by default hashable 2019-04-04 20:11:53 +13:00
ben
0bd08618af Change _py_abc to workaround current issue, and run test with PYTHONPATH
linking to Lib directory.
2019-04-04 20:11:53 +13:00
ben
39d4d64a4c Copy abc and dependent python files over from CPython 3.7 branch 2019-04-04 20:11:53 +13:00
Rachel Powers
fa53d5cd65 impl list.__delitem__ using list.__setitem__ as a guide
while it works as well as __setitem__ currently does this impliments no
support for slice indexing or negative indexing, adtionaly a bad index
panics insted of giving a vm type error!
2019-04-03 21:11:03 -06:00
Joey Hain
88bf2a32c4 address feedback 2019-04-03 17:30:04 -07:00
Windel Bouwman
29a137bf0f Drop testlist2. Also add test cases for trailing comma in for statement and tuple addition example. 2019-04-03 22:24:19 +02:00
coolreader18
c6e875f209 Merge pull request #773 from RustPython/coolreader18/whats_left-overhaul
Redo much of whats_left_to_implement.py
2019-04-03 10:29:33 -05:00
coolreader18
e078614e05 Change to classes and remove unnecesary if 2019-04-03 08:50:55 -05:00
Windel Bouwman
23f57f757c Improve trailing comma situation 2019-04-03 14:08:12 +02:00
Windel Bouwman
a59db050ac Merge pull request #776 from adrian17/comparisons
Support chained comparisons
2019-04-03 09:17:11 +02:00
Joey
1e7ca4cac3 Merge pull request #777 from RustPython/joey/convert-complex
Convert complex to new args style
2019-04-02 22:35:34 -07:00
Adrian Wielgosik
2fb3fc92ec Support chained comparisons 2019-04-02 23:22:54 +02:00
Joey
6863c19fb7 complex: convert to new args style 2019-04-02 09:51:06 -07:00
Joey
75d02a1725 complex: move to impl block 2019-04-02 09:30:18 -07:00
ben
ea2622ee7b Make slice.stop not an option 2019-04-02 17:25:51 +13:00
coolreader18
d81533befa Merge branch 'master' into coolreader18/whats_left-overhaul 2019-04-01 23:20:47 -05:00
coolreader18
a77b3489b7 Merge pull request #764 from RustPython/coolreader18/py_class-proc-macro
Add #[py_class] attribute proc macro
2019-04-01 23:17:38 -05:00
Joey Hain
8549ea22a3 Use match_class! in objint::to_int 2019-04-01 20:22:11 -07:00
Joey Hain
98889d5339 match_class! macro 2019-04-01 20:09:45 -07:00
coolreader18
9ff1e41422 Give values instead of types, list comprehension, remove methods not in CPython 2019-04-01 18:28:15 -05:00
coolreader18
6276241d59 Redo much of whats_left_to_implement.py 2019-04-01 18:12:28 -05:00
Windel Bouwman
0ce15e1ff5 Merge pull request #772 from adrian17/iterables
Refactor iterables, separate types, make behavior more compatible with CPython
2019-04-01 21:45:15 +02:00
Adrian Wielgosik
2f2a8438b5 Add iterable tests 2019-04-01 19:45:20 +02:00
Adrian Wielgosik
de5b1c4055 Support iter() for types with only __getitem__ 2019-04-01 19:45:16 +02:00
Adrian Wielgosik
c918e9d5d3 Split iterators into separate types 2019-04-01 19:45:14 +02:00
Adrian Wielgosik
bbfca26b27 Move PyIteratorValue to objiter.rs 2019-04-01 19:45:10 +02:00
Adrian Wielgosik
cba8aa9be5 Drop iter_type_init, explicitly define __iter__ for iterators 2019-04-01 19:45:07 +02:00
Adrian Wielgosik
016ecf204d Move iterator __contains__ to 'in' implementation 2019-04-01 19:45:00 +02:00
coolreader18
b3ea8155a5 Don't clone 2019-03-31 22:40:57 -05:00
coolreader18
43b0760173 Merge branch 'master' into coolreader18/py_class-proc-macro 2019-03-31 21:16:25 -05:00
coolreader18
51b766089f Allow an enum with #[pyclass] 2019-03-31 19:53:52 -05:00
coolreader18
42768b20e5 Small demo improvements 2019-03-31 17:53:53 -05:00
coolreader18
53b46a7b32 Split some of #[pyclass] off into #[pyimpl] 2019-03-31 17:23:33 -05:00
Windel Bouwman
aede03c1b2 Merge pull request #762 from palaviv/doc
Support class and function __doc__
2019-03-31 20:01:05 +02:00
Aviv Palivoda
4e99350e5c Use StoreAttr for __doc__ 2019-03-31 18:52:27 +03:00
Aviv Palivoda
6d53fe6924 Add more tests for class doc 2019-03-31 18:52:27 +03:00
Aviv Palivoda
ab3cde77b4 Support class __doc__ 2019-03-31 18:52:27 +03:00
Aviv Palivoda
c76b31866d Add more tests for function doc 2019-03-31 18:52:27 +03:00
Aviv Palivoda
f994f8660e Function support __doc__ 2019-03-31 18:51:57 +03:00
Windel Bouwman
69c81730d3 Merge pull request #760 from RustPython/parser-fixes
Add support for trailing comma in function defs. Parser code simplica…
2019-03-31 10:57:51 +02:00
Windel Bouwman
f1a60e1ce5 Merge pull request #769 from RustPython/coolreader18/lalrpop-process-out_dir
Process lalrpop in cargo's target directory
2019-03-31 10:57:31 +02:00
coolreader18
60ad5489f1 Ignore clippy lints in the lalrpop generated file 2019-03-30 22:58:46 -05:00
coolreader18
1b57f07834 Process lalrpop in cargo's target directory 2019-03-30 22:56:37 -05:00
coolreader18
15cffc4d2b Clean up a bit 2019-03-30 22:30:14 -05:00
coolreader18
f11f04da70 Split rustpython_derive into multiple files 2019-03-30 18:43:31 -05:00
ben
e0f7fbb191 Don't derive FromArgs on payload type. 2019-03-31 10:53:45 +13:00
Joey
cb0b6a80c5 Merge pull request #759 from RustPython/joey/convert-bytes
Convert bytes to new args style
2019-03-30 14:48:43 -07:00
ben
a49895ef63 Cleanup slice_new and added more slice tests 2019-03-31 09:58:02 +13:00
ben
5625f7e15e Allow arbitrary in slice, and convert slice.__new__ to new style 2019-03-31 09:58:02 +13:00
jgirardet
7d18a1ce60 Fix #746: invalid slice with start or stop =-1 when step<0 2019-03-30 21:47:20 +01:00
Joey Hain
c2d04f97d8 bytes: add tests for NotImplemented 2019-03-30 13:33:50 -07:00
Joey Hain
83c1d4fe10 Merge remote-tracking branch 'origin/master' into joey/convert-bytes 2019-03-30 13:31:43 -07:00
coolreader18
d9efe4ea37 Require a #[pymethod] for a method to be recognized 2019-03-29 16:16:31 -05:00
coolreader18
8376ec2d98 Use doc comments for python __doc__ 2019-03-29 15:17:58 -05:00
coolreader18
ab6031871c impl PyStringRef using py_class 2019-03-29 14:51:42 -05:00
coolreader18
4222d87e31 Merge branch 'master' into coolreader18/py_class-proc-macro 2019-03-29 13:55:08 -05:00
Joey
c5c91818a5 Merge pull request #755 from skinny121/int_new_args
Use new style args for int.__new__
2019-03-29 09:13:25 -07:00
coolreader18
c724fdaabe Merge pull request #761 from adrian17/re
Convert re to new style args
2019-03-29 10:58:11 -04:00
ben
ce9a909b9d Change kind identifier to fully use python terminology 2019-03-29 19:03:13 +13:00
ben
b5dc5a28e7 Merge branch 'master' into int_new_args
# Conflicts:
#	vm/src/function.rs
2019-03-29 18:51:19 +13:00
coolreader18
ff85838556 Add #[py_class] attribute proc macro 2019-03-29 00:16:34 -05:00
coolreader18
6618def266 Merge pull request #763 from adrian17/more-args
Convert more functions to new args style
2019-03-28 19:10:03 -04:00
Adrian Wielgosik
8f1ec3dd23 Convert slice::{start, stop, stop} to new args style 2019-03-28 23:08:46 +01:00
Adrian Wielgosik
d5e2b3a8b6 Convert iterators next() to new args style
Except objiter, as it'll need to be reworked anyway
2019-03-28 23:08:46 +01:00
Adrian Wielgosik
792c6a103e Convert re to new style args 2019-03-28 21:32:18 +01:00
Windel Bouwman
73cd680d8d Add support for trailing comma in function defs. Parser code simplications. 2019-03-28 17:50:41 +01:00
Joey
149aefe470 Merge pull request #757 from RustPython/joey/convert-bytearray
bytearray: convert to new args style
2019-03-28 08:16:49 -07:00
Joey
da4df08516 Merge pull request #758 from RustPython/joey/convert-builtins
Convert some builtin fns to new args style
2019-03-28 08:16:35 -07:00
coolreader18
e1865fed82 Merge pull request #743 from RustPython/coolreader18/update-deps
Update cargo dependencies
2019-03-28 11:16:21 -04:00
ben
6fd6cc647b Renamed ArgKind, and member to be consistent with python inspect module 2019-03-28 22:00:55 +13:00
ben
c8f4474e7f Implement handling of optional attribute in proc macro 2019-03-28 21:46:26 +13:00
ben
657d025592 Change syntax of attributes in FromArgs proc macro 2019-03-28 21:34:11 +13:00
coolreader18
b621a13415 Merge branch 'master' into coolreader18/update-deps 2019-03-27 22:32:42 -04:00
Joey Hain
e0aca86473 bytes: convert methods to new args style 2019-03-27 19:23:23 -07:00
Joey Hain
e4272126cf bytes: return NotImplemented where appropriate 2019-03-27 19:15:38 -07:00
Joey Hain
b0d7960cc5 bytes: move methods to impl block 2019-03-27 19:14:37 -07:00
Joey Hain
62842e6d19 convert some builtins 2019-03-27 19:01:13 -07:00
Joey
57fa041d08 bytearray: convert to new args style 2019-03-27 18:55:56 -07:00
Joey
e048037146 Merge pull request #756 from adrian17/objobject
Convert objobject.rs to new args style
2019-03-27 17:51:20 -07:00
Adrian Wielgosik
89f63e4c9a Convert objobject.rs to new args style 2019-03-27 23:25:09 +01:00
Windel Bouwman
c2eb6643f3 Merge pull request #754 from adrian17/master
Upgrade lalrpop
2019-03-27 21:09:01 +01:00
Adrian Wielgosik
40dd75d513 Upgrade lalrpop 2019-03-27 18:55:08 +01:00
ben
3ca387b509 Enhance FromArgs derive proc macro to allow positional, and positional
or keyword arguments.
2019-03-28 05:55:15 +13:00
Windel Bouwman
1cda87a239 Merge pull request #752 from RustPython/more_dict_cleanup
More dict cleanup
2019-03-27 15:53:14 +01:00
Adam Kelly
c644176547 Modules have attributes, not items. 2019-03-27 10:53:08 +00:00
Adam Kelly
4cb7f026de Remove unnecessary cast to pyobject in kwarg construction. 2019-03-27 10:53:08 +00:00
Windel Bouwman
14d3aab528 Merge pull request #753 from adrian17/master
Remove .gcno files before a coverage run
2019-03-26 19:34:05 +01:00
Adrian Wielgosik
c5203a4934 Remove .gcno files before a coverage run 2019-03-26 19:00:06 +01:00
Joey
5ef8220d20 Merge pull request #751 from RustPython/scope_holds_dictionaries
Change types inside Scope to PyDictRef.
2019-03-26 09:33:31 -07:00
Adam Kelly
4a5592d461 Change types inside Scope to PyDictRef. 2019-03-26 15:16:49 +00:00
Adam
e68eb9c409 Merge pull request #750 from RustPython/joey/cleanup-type-protocol
Clean up type protocol
2019-03-26 12:00:12 +00:00
Joey Hain
625d2357bd Fix wasm 2019-03-25 19:34:24 -07:00
Joey Hain
8bdc766bed Use name field directly 2019-03-25 19:32:58 -07:00
Joey Hain
6474a4a6ef Remove objtype::get_type_name() 2019-03-25 19:18:07 -07:00
Joey Hain
cc4f3fdb40 Clean up TypeProtocol 2019-03-25 19:18:01 -07:00
coolreader18
e819ca6b87 Merge branch 'master' into coolreader18/update-deps 2019-03-25 21:41:32 -04:00
coolreader18
ac2a5e281c Add comment explaining bytes -> Uint8Array conversion 2019-03-25 19:37:16 -05:00
Adam Kelly
17b816fbf8 Fix objset compilation error caused by merge race. 2019-03-25 20:37:47 +00:00
Adam
cac9da4c35 Merge pull request #748 from RustPython/attributes_and_dictionaries
Attributes and dictionaries
2019-03-25 20:30:46 +00:00
Windel Bouwman
20c09f025a Merge pull request #747 from adrian17/master
Update grcov
2019-03-25 20:41:39 +01:00
Windel Bouwman
6ae10ed938 Fix build and add extend_class macro usage for set and frozenset 2019-03-25 20:23:13 +01:00
Windel Bouwman
983be0f944 Merge pull request #725 from palaviv/frozen-set-2
frozenset
2019-03-25 19:54:52 +01:00
Windel Bouwman
e47032f9e4 Merge pull request #749 from adrian17/tests-cleanup
Tests cleanups
2019-03-25 19:38:11 +01:00
Adrian Wielgosik
2131a8130c Clean up some tests 2019-03-25 17:59:51 +01:00
Adrian Wielgosik
16e04cf298 Run rustpython tests without cargo middleman 2019-03-25 17:54:04 +01:00
Adrian Wielgosik
4ab59a8e4c Do not run benchmarks in the main test suite 2019-03-25 17:53:13 +01:00
Adrian Wielgosik
e44b02b88f Avoid trace log in tests 2019-03-25 17:52:37 +01:00
Adam Kelly
55e0fb1f19 AST class for nodes instead of just using object everywhere. 2019-03-25 16:39:25 +00:00
Adam Kelly
bbb7162472 Various dictionary changes.
* vm.ctx.new_dict returns a PyDictRef
* Special case for module goes away.
* Instances get a real dictionary.
2019-03-25 16:37:20 +00:00
Adrian Wielgosik
602f2a83da Update grcov 2019-03-25 17:35:21 +01:00
Adam Kelly
17c3f9f024 builtin_locals can just return a reference to the locals dict. 2019-03-25 16:34:07 +00:00
Adam Kelly
3562b8f59c Store class attributes inside PyClass struct. 2019-03-25 11:21:01 +00:00
Adam
9989795141 Merge pull request #742 from RustPython/emoji-support
Doing what is needed for all our non-latin friends.
2019-03-25 10:39:09 +00:00
Windel Bouwman
ca11e7dea7 Add support for emoji as name. 2019-03-24 20:16:38 +01:00
Joey
0409e8197b Merge pull request #744 from RustPython/joey/range-new-style
Convert range to new args style
2019-03-24 11:49:34 -07:00
Joey
f2d562a4cc pyint: use as_bigint() everywhere 2019-03-24 10:05:25 -07:00
Joey
9a0113deed range: represent w/ int refs 2019-03-24 09:59:06 -07:00
Joey
c2e1e9b0dc Convert range to new args style 2019-03-24 09:59:06 -07:00
coolreader18
565719dcda Update cargo dependencies 2019-03-24 11:26:41 -05:00
coolreader18
3b582760b4 Merge pull request #733 from RustPython/coolreader18/wasm-browser-dom
[WASM] Add PyDocument and PyElement classes to browser
2019-03-24 10:47:46 -05:00
Joey
9d78fa5df2 Merge pull request #719 from adrian17/type-subclasses
Type __subclasses__()
2019-03-24 08:22:11 -07:00
coolreader18
6450612bdf Merge branch 'master' into coolreader18/wasm-browser-dom 2019-03-24 08:54:51 -05:00
coolreader18
0ac1c1f19c Add line continuation for the WASM demo terminal 2019-03-24 08:42:18 -05:00
Windel Bouwman
d0c4fcb2fa Doing what is needed for all our non-latin friends. 2019-03-24 13:14:38 +01:00
Adrian Wielgosik
e39df6daef Basic implementation of T.__subclasses__().
Ideally, the weak list should be updated whenever a type is removed,
and the list shouldn't be a Vec, but this should be good enough for
starters.
2019-03-24 12:49:04 +01:00
Adrian Wielgosik
a895ab35ae Make PyWeak::downgrade take a reference 2019-03-24 11:56:15 +01:00
Adrian Wielgosik
9a6f7aa8a1 Make PyRef::clone not require T implementing Clone
It seems to be a weird consequence of using PhantomData,
so I just rolled a custom Clone.
2019-03-24 11:56:15 +01:00
Joey
fbd0860f1b Merge pull request #740 from skinny121/into_object_cleanup
Use specific PyRef where possible - code object/type_new_class
2019-03-23 21:28:39 -07:00
coolreader18
12564da369 Rustfmt? 2019-03-23 22:46:21 -05:00
coolreader18
ec433cdbb9 Fix rustfmt again (?) 2019-03-23 22:17:21 -05:00
ben
3f363585e8 Panic if value poped of stack isn't a code object. 2019-03-24 16:08:17 +13:00
Joey
5441f3f89c Merge pull request #739 from RustPython/joey/range-getitem-either
Introduce Either extractor and convert range.__getitem__
2019-03-23 19:10:37 -07:00
coolreader18
946103bca8 Merge branch 'master' into coolreader18/wasm-browser-dom 2019-03-23 20:12:26 -05:00
Joey
84d47d21cf Rename to just Either 2019-03-23 17:51:12 -07:00
ben
6eb93a7000 Move code methods into impl PyCodeRef 2019-03-24 13:50:50 +13:00
coolreader18
0f2889a0e5 Fix weird rustfmt 2019-03-23 19:46:46 -05:00
ben
db8e648646 Make PyFunction.code a PyCodeRef, PyGenerator.frame a FrameRef, and
other improvements to increase use of specific ref types.
2019-03-24 13:41:37 +13:00
ben
dc68101577 Refactor type_new_class to use more specific ref types 2019-03-24 12:08:15 +13:00
Joey
3c15d892c5 Avoid some cloning 2019-03-23 15:57:06 -07:00
Joey
e5066da94e Merge remote-tracking branch 'origin/master' into joey/range-getitem-either 2019-03-23 15:50:12 -07:00
Joey
b6f1ecdb4b Fix example 2019-03-23 15:49:31 -07:00
Joey
a1560103ea Merge pull request #737 from skinny121/object_type_pyclassref
Change PyObject.typ to PyClassRef
2019-03-23 15:41:19 -07:00
Joey
a5558e0e32 Introduce Either extractor and convert range.__getitem__ 2019-03-23 15:05:12 -07:00
ben
faf1925a25 Remove usages of PyClassRef::from_pyobj 2019-03-24 10:51:52 +13:00
ben
00540dec35 Fix wasm, to reflect that PyObject.typ is now a PyClassRef 2019-03-24 10:51:52 +13:00
ben
6fa059fd6c Make PyObject.typ a PyClassRef 2019-03-24 10:51:52 +13:00
Joey
4666a09b20 Merge pull request #735 from RustPython/joey/range-cleanup
Range cleanups
2019-03-23 14:35:18 -07:00
Aviv Palivoda
590b659548 Change validate_set_or_frozenset to a function 2019-03-23 23:24:57 +02:00
Joey
da3dfa6c03 Merge pull request #734 from RustPython/joey/socket-cleanup
Some socket and io cleanups
2019-03-23 14:18:14 -07:00
Joey
3177824474 Fix test- 2019-03-23 12:57:17 -07:00
Joey
18ed00a653 Range cleanups 2019-03-23 12:48:37 -07:00
Joey
e4e7da3d54 Some socket cleanups 2019-03-23 12:21:55 -07:00
coolreader18
cecc2e1835 Merge pull request #732 from palaviv/super-classmethod
Support classmethod super
2019-03-23 14:17:06 -05:00
coolreader18
0aabe88c5d Put browser class methods into impl blocks 2019-03-23 14:04:14 -05:00
coolreader18
9050799cc4 Merge branch 'master' into coolreader18/wasm-browser-dom 2019-03-23 13:22:07 -05:00
Joey
65e00a8f32 Merge pull request #730 from RustPython/joey/remove-frompyobjecterf
Remove FromPyObjectRef, replace with downcast
2019-03-23 11:05:10 -07:00
Aviv Palivoda
1d820a9586 Use payload_is 2019-03-23 20:01:11 +02:00
Aviv Palivoda
2f9a49d077 Support classmethod super 2019-03-23 19:56:00 +02:00
Joey
af0194d51e Merge pull request #731 from RustPython/cleaning-tweaks
Use extend_class macro even more
2019-03-23 10:49:09 -07:00
Joey
f413beb051 Fix test 2019-03-23 10:03:40 -07:00
Windel Bouwman
fa8d3524bf Use extend_class macro even more 2019-03-23 17:49:49 +01:00
Joey
2aee2981e3 Remove FromPyObjectRef, replace with downcast 2019-03-23 09:38:03 -07:00
Aviv Palivoda
dc05d5f94b Remove Refcell around PyFrozenSet elements 2019-03-23 17:28:50 +02:00
Aviv Palivoda
2626a800ab Support frozenset 2019-03-23 17:27:33 +02:00
coolreader18
a830d8e131 Add PyDocument and PyElement 2019-03-23 09:36:15 -05:00
coolreader18
430bc4bac2 Fix vm.import when there are no frames on stack 2019-03-23 09:35:53 -05:00
Windel Bouwman
9b4d719197 Merge pull request #728 from RustPython/remove_attribute_protocol
Remove attribute protocol
2019-03-23 13:13:34 +01:00
Adam Kelly
441560b691 Delete Attribute Protocol. 2019-03-23 11:29:22 +00:00
Adam Kelly
386f90fa25 Remove PyContext.get_attr. 2019-03-23 11:29:22 +00:00
Windel Bouwman
9630c5cee1 Merge pull request #727 from RustPython/wasm_no_attribute_protocol
Remove attribute protocol from wasm.
2019-03-23 12:13:02 +01:00
Windel Bouwman
8fa315110e Merge pull request #726 from RustPython/bool_magic_methods
Replace special cases in boolval with __bool__ method on types.
2019-03-23 11:41:36 +01:00
Adam Kelly
c8bdb249b0 Remove attribute protocol from wasm. 2019-03-23 10:11:39 +00:00
Adam Kelly
9ebbde8126 Replace special cases in boolval with __bool__ method on types. 2019-03-23 09:31:42 +00:00
Adam
26a238085f Merge pull request #724 from RustPython/cleaning-tweaks
Increase usage of extend_class macro.
2019-03-23 09:14:50 +00:00
Adam
cea5341473 Merge pull request #723 from skinny121/isinstance_classref
Change isinstance/issubclass to accept PyClassRef
2019-03-23 09:14:16 +00:00
Windel Bouwman
b93f96d491 Increase usage of extend_class macro. 2019-03-23 09:16:32 +01:00
ben
983cb9e886 Fix Never::class signature 2019-03-23 19:35:42 +13:00
ben
4e7e503785 Fix wasm build, to reflect that isinstance now takes a PyClassRef 2019-03-23 19:32:31 +13:00
ben
ad584df120 Allow context.set_attr to accept PyRef values in addition to PyObjectRef 2019-03-23 19:32:31 +13:00
ben
c1d5ce715f Change isinstance/issubclass to accept PyClassRef instead of PyCObject.
Also changed PyValue::class to return a PyClassRef.
2019-03-23 19:32:31 +13:00
Joey
b7fa08eb36 Merge pull request #722 from RustPython/joey/unboxed-payload-2
Remove Box from PyObject
2019-03-22 20:29:36 -07:00
Joey
3f98a8ab1b Merge pull request #721 from skinny121/context_ref_types
Change types in PyContext to be PyClassRef's than PyObjectRef's
2019-03-22 19:14:01 -07:00
Joey
050bf0730e Remove HeldRcInner 2019-03-22 19:10:22 -07:00
Joey Hain
85ffde7382 Fix wasm 2019-03-22 18:37:06 -07:00
Joey Hain
c06b1c70df Fix merge issue 2019-03-22 18:05:24 -07:00
Joey Hain
7b4b0979f4 Merge remote-tracking branch 'origin/master' into joey/unboxed-payload-2 2019-03-22 18:04:15 -07:00
Joey Hain
bb161a5a67 Remove Box from PyObject 2019-03-22 18:04:09 -07:00
ben
b354b86b7b Fix none_new, return same object that is in PyContext 2019-03-23 13:00:17 +13:00
ben
5c7812734d Use more specific ref type than PyObjectRef in PyContext 2019-03-23 13:00:12 +13:00
coolreader18
79a7aed46d Make logo larger 2019-03-22 18:12:08 -05:00
coolreader18
c430b5a597 Fix logo in README 2019-03-22 18:10:46 -05:00
coolreader18
cf78d6b3eb Add logo to README 2019-03-22 18:09:05 -05:00
Adam
52943bf73c Merge pull request #710 from RustPython/class_get_attr_2
Class get attr 2
2019-03-22 22:21:55 +00:00
Joey
bcc3aa0910 Merge pull request #720 from RustPython/cleaning-tweaks
Use the extend class macro more.
2019-03-22 13:56:39 -07:00
Adam Kelly
c67cb07d9d Rename class_has_item and class_has_attr. 2019-03-22 20:54:14 +00:00
Adam Kelly
50437f8a75 Use class_get_attr in various places where we need the internal interface 2019-03-22 19:51:02 +00:00
Adam Kelly
909b38e774 Adapt objobject to avoid AttributeProtocol. 2019-03-22 19:49:09 +00:00
Adam Kelly
66adc25201 objtype - replace AttributeProtocol access with class_get_attr. 2019-03-22 19:47:51 +00:00
Windel Bouwman
68ba050030 Use the extend class macro more. 2019-03-22 20:45:34 +01:00
coolreader18
8f6d8a78de Keepalive WASM webpack build 2019-03-22 13:14:08 -05:00
coolreader18
162c2dc207 Merge branch 'coolreader18/multiline-repl'
Make the REPL handle line continuation better #711
2019-03-22 11:27:05 -05:00
Windel Bouwman
7ed4bc4aa8 Merge pull request #698 from palaviv/super
Use first argument in super
2019-03-22 17:13:13 +01:00
Aviv Palivoda
2c8657c3b3 Add load_cell to NameProtocol 2019-03-22 16:37:28 +02:00
Aviv Palivoda
84e89d37e2 Use __class__ cell in super 2019-03-22 16:37:28 +02:00
Aviv Palivoda
6230a25c4b Use first argument in super 2019-03-22 16:37:28 +02:00
coolreader18
5e74d53fb4 Merge pull request #716 from palaviv/fix-format
Fix format
2019-03-22 09:32:54 -05:00
Aviv Palivoda
474577beca Fix format 2019-03-22 16:23:15 +02:00
coolreader18
a9e2cc90d4 Merge pull request #714 from RustPython/coolreader18/immutable-vm-ref
Convert all &mut VirtualMachine to &VirtualMachine
2019-03-22 07:36:45 -05:00
coolreader18
18be23a2ec Merge branch 'master' into coolreader18/multiline-repl 2019-03-22 07:29:53 -05:00
coolreader18
36ff4e37d3 Use vm.get_attribute 2019-03-22 07:29:14 -05:00
coolreader18
5c8c4a849d Merge branch 'master' into coolreader18/multiline-repl 2019-03-22 07:27:10 -05:00
coolreader18
79666c255a Fix some issues wrt mutability 2019-03-22 07:24:06 -05:00
coolreader18
b0d8935731 Merge branch 'master' into coolreader18/immutable-vm-ref 2019-03-22 07:21:45 -05:00
Adam
e7eff34e13 Merge pull request #709 from RustPython/avoid_attribute_protocol
Avoid attribute protocol
2019-03-22 11:42:30 +00:00
Adam Kelly
23ee751880 Use vm.get_attribute to access attributes of modules. 2019-03-22 10:54:28 +00:00
coolreader18
2c93c79ac8 Immutable prompt variable 2019-03-22 01:53:55 -05:00
coolreader18
243826679c Remove unnecessary &mut 2019-03-22 01:51:44 -05:00
coolreader18
a9051ab462 Convert all &mut VirtualMachine to &VirtualMachine 2019-03-22 01:48:14 -05:00
Windel Bouwman
0838e301c7 Merge pull request #706 from RustPython/immutable-vm
Put RefCell around frames member of VirtualMachine.
2019-03-22 07:06:18 +01:00
coolreader18
88d6926f78 Make the REPL handle continuation better 2019-03-21 20:25:16 -05:00
Windel Bouwman
08520a68cf Merge pull request #700 from RustPython/coolreader18/wasm-example-npm
Change the WASM example to use rustpython from npm
2019-03-21 18:40:20 +01:00
Joey
90db9812e5 Merge pull request #707 from RustPython/joey/proper-pyref-display
Fix the Display impl for PyRef
2019-03-21 09:32:02 -07:00
Adam Kelly
19fc202e1a Classmethod/staticmethod - rewrite using structs and new style methods. 2019-03-21 13:03:51 +00:00
Adam
ce120c13b7 Merge pull request #705 from RustPython/into_pystringref
Introduce IntoPyStringRef to make vm.get_attribute more usable.
2019-03-21 12:13:19 +00:00
Adam Kelly
e66b5078a8 Introduce TryIntoRef<T> to make vm.get_attribute more usable. 2019-03-21 10:58:32 +00:00
Joey
59807710f7 Merge remote-tracking branch 'origin/master' into joey/proper-pyref-display 2019-03-21 03:43:40 -07:00
Adam
5a1a436c1e Merge pull request #708 from skinny121/descriptor_set_delete
Implement calling __set__ and __delete__ magic methods
2019-03-21 10:43:10 +00:00
ben
4ad8d5ed9b Make property.__get__ owner parameter optional 2019-03-21 19:57:35 +13:00
ben
a5f6a7b10d Implement calling __set__ and __delete__ 2019-03-21 19:34:47 +13:00
coolreader18
f5bbc7f664 Merge pull request #701 from RustPython/coolreader18/fix-wasm-import-json
Fix the WASM build
2019-03-21 01:01:02 -05:00
coolreader18
ed60b19612 Use vm.{,de}serialize in rustpython_wasm 2019-03-21 00:10:02 -05:00
coolreader18
d024e7ed8d Switch from an stdlib function to a vm method 2019-03-21 00:08:36 -05:00
coolreader18
7a980b3b47 Merge branch 'master' into coolreader18/fix-wasm-import-json 2019-03-20 23:58:19 -05:00
Joey Hain
0b1b6682c1 Fix Display impl for PyRef 2019-03-20 18:32:25 -07:00
Joey Hain
54753b3d14 list, tuple: return NotImplemented for unsupported comparisons 2019-03-20 18:32:08 -07:00
Windel Bouwman
8c0419e6b4 Put RefCell around frames member of VirtualMachine. This allows for VirtualMachine to be immutable. 2019-03-20 20:29:08 +01:00
coolreader18
6c660c9a6f Merge pull request #699 from RustPython/coolreader18/fix-clippy1
Fix a bunch of clippy lints (again)
2019-03-20 09:03:41 -05:00
coolreader18
3731148237 Merge branch 'master' into coolreader18/fix-clippy1 2019-03-20 09:03:07 -05:00
coolreader18
e35cc813a8 Rename to Unnamed and Named 2019-03-20 08:59:37 -05:00
Windel Bouwman
4c485202d1 Merge pull request #703 from RustPython/add_class_cell
Add __class__ cell to method scopes.
2019-03-20 13:56:03 +01:00
Adam Kelly
1958e47022 Add __class__ cell to method scopes. 2019-03-20 09:20:28 +00:00
Adam
32cb59909e Merge pull request #694 from skinny121/setattr
Various fixes for getattr/setattr/hasattr
2019-03-20 08:35:00 +00:00
ben
08e66b5002 Create workaround for properties on None 2019-03-20 19:58:56 +13:00
ben
a5050ebafe Make property return itself if invoke by class binding 2019-03-20 19:58:54 +13:00
ben
6c3a402eca Fix setting attributes on modules 2019-03-20 19:58:48 +13:00
ben
48dd507cad Remove dict from object 2019-03-20 19:58:46 +13:00
ben
c77b1f3cf5 Fix bug with __getattr__ 2019-03-20 19:56:25 +13:00
ben
63d40edbc6 Added bunch af attribute has/get/set/delete tests and fixed getattr and
hasattr handling of exceptions.
2019-03-20 19:56:23 +13:00
ben
4e42bd077c Implement __setattr__ based on @nhynes(#540) PR 2019-03-20 19:53:50 +13:00
coolreader18
de1bc937e7 Use json straight from json.rs 2019-03-19 22:20:10 -05:00
coolreader18
b7916cdb53 Fix varargs errors 2019-03-19 22:15:09 -05:00
coolreader18
ef3b9105ef Rename object_is back to payload_is 2019-03-19 20:59:48 -05:00
coolreader18
01bed2a051 Change the WASM example to use rustpython from npm 2019-03-19 20:54:53 -05:00
coolreader18
33b99b203f Some minor things 2019-03-19 20:34:35 -05:00
coolreader18
ff5c203b0e impl From<&ast::Varargs> for bytecode::Varargs 2019-03-19 20:13:03 -05:00
coolreader18
b30d56df29 Fix some more clippy warnings 2019-03-19 20:02:06 -05:00
coolreader18
ab53883f67 Change varargs from Option<Option<_>> to its own enum 2019-03-19 19:53:22 -05:00
coolreader18
4c9527be47 Merge branch 'master' into coolreader18/fix-clippy1 2019-03-19 19:19:36 -05:00
Windel Bouwman
5b6b33b644 Merge pull request #697 from RustPython/more_pyobject
More pyobject
2019-03-19 19:21:44 +01:00
Windel Bouwman
415f44da79 Merge pull request #673 from RustPython/string-io
Add write method to io.StringIO
2019-03-19 19:12:08 +01:00
Windel Bouwman
1969c90d98 Merge pull request #696 from palaviv/super
super in class methods
2019-03-19 19:08:53 +01:00
Adam Kelly
5384e07bf3 Remove PyObject::new from tuple and list. 2019-03-19 17:15:14 +00:00
Adam Kelly
c6e7d8901f Remove use of PyObject::new from objset. 2019-03-19 17:14:51 +00:00
Adam Kelly
638196bce4 Eliminate PyObject::new from objenumerate. 2019-03-19 16:42:40 +00:00
Adam Kelly
d38e89a811 Remove PyObject::new from objgenerator. 2019-03-19 16:28:53 +00:00
Adam Kelly
aeaa94966f Remove PyObject::new from objmap. 2019-03-19 16:24:19 +00:00
Aviv Palivoda
c3d0fddfcf Add PySuper 2019-03-19 18:08:43 +02:00
coolreader18
f78f558404 Fix clippy lints 2019-03-19 10:52:39 -05:00
Adam
4b5e75ea5b Merge pull request #683 from RustPython/objdict_refactor
Objdict refactor
2019-03-19 11:24:21 +00:00
Adam Kelly
6b3f61f3ca Merge branch 'master' into objdict_refactor 2019-03-19 10:19:03 +00:00
Aviv Palivoda
50cc9fa91f super works in class methods 2019-03-18 22:00:54 +02:00
Windel Bouwman
76dbd8c6e8 Apply cargo formatting. 2019-03-18 20:21:35 +01:00
Windel Bouwman
ac2aecd6fe Disable file argument in test. 2019-03-18 20:00:55 +01:00
Windel Bouwman
18fc8c150b Merge master 2019-03-18 20:00:00 +01:00
Windel Bouwman
3191725022 Refactor into new-style PyObject 2019-03-18 17:48:46 +01:00
Joey
c57be01711 Merge pull request #691 from RustPython/joey/builtin-print-newargs
Convert print() builtin to new args style
2019-03-18 09:35:46 -07:00
Windel Bouwman
39ee9172ff Merge pull request #693 from RustPython/joey/just-use-pyfuncargs
FromArgs: use PyFuncArgs instead of iterator
2019-03-17 07:34:59 +01:00
Joey
18b57188ba Add a custom derive for FromArgs 2019-03-16 17:13:23 -07:00
Joey
7cb889d42c Rebase against #693 and simplify 2019-03-16 16:38:28 -07:00
Joey
6550c52fa9 None doesn't mean no sep/end 2019-03-16 16:29:09 -07:00
Joey
55e7982835 Don't need while let 2019-03-16 16:29:09 -07:00
Joey
e83686cf3c Add clarifying note to KwArgs docs 2019-03-16 16:29:09 -07:00
Joey
d3b9714754 Convert print() builtin to new args style 2019-03-16 16:29:09 -07:00
Joey
7be5b8dafe FromArgs: use PyFuncArgs instead of iterator 2019-03-16 16:07:59 -07:00
Joey
3242ff3003 Merge pull request #690 from RustPython/joey/kwargs-surprise-positional
Handle unexpected positional argument in KwArgs
2019-03-16 12:58:35 -07:00
Joey
60ed1bd0a7 Handle unexpected positional argument in KwArgs 2019-03-16 10:18:46 -07:00
Joey
a32ebd530e Merge pull request #688 from RustPython/joey/pyobject-function-split
Move function items out of pyobject module
2019-03-16 09:15:51 -07:00
Joey
9de7285d23 Merge remote-tracking branch 'origin/master' into joey/pyobject-function-split
Conflicts:
      vm/src/frame.rs
      vm/src/obj/objbytearray.rs
      vm/src/obj/objbytes.rs
      vm/src/obj/objcomplex.rs
2019-03-16 08:37:18 -07:00
Adam
94e3cb8363 Merge pull request #682 from RustPython/prefer_pyvalue_into_ref
Prefer pyvalue into ref
2019-03-16 10:14:21 +00:00
Adam Kelly
9eeeeeae48 Change return type of vm.to_repr and vm.to_str to PyStringRef. 2019-03-16 09:42:54 +00:00
Adam Kelly
2f5c3ef1df Use PyStringRef to check type of dictionary keys. 2019-03-16 09:42:54 +00:00
Adam Kelly
a718a5a723 Refactor dict methods to new style declarations. 2019-03-16 09:42:54 +00:00
Adam Kelly
da6c56a001 Use extend_class in declaration of dictionary. 2019-03-16 09:22:02 +00:00
Adam Kelly
1f1b48c612 into_ref now needs the vm rather than a context. 2019-03-16 09:21:12 +00:00
Windel Bouwman
dbce329190 Merge pull request #687 from chylli/fix-any-memory-leak
#639
2019-03-16 10:18:27 +01:00
Chylli
6923490afc more test 2019-03-16 13:55:29 +08:00
Chylli
40a4e373af try 2019-03-16 13:52:57 +08:00
Chylli
144a8ae179 more test 2019-03-16 13:33:14 +08:00
Joey
7bfd2e6e84 Move function items out of pyobject module 2019-03-15 21:27:11 -07:00
Chylli
cf82a256da test any 2019-03-16 11:16:09 +08:00
Adam
0e6e8b617d Merge branch 'master' into prefer_pyvalue_into_ref 2019-03-15 22:11:51 +00:00
Windel Bouwman
7a4d653268 Merge pull request #679 from RustPython/joey/vm-not-pycontext
Make it possible to implement PyValue in stdlib
2019-03-15 19:23:39 +01:00
Windel Bouwman
bbe2704678 Merge pull request #684 from palaviv/selenium
Selenium tests for WASM
2019-03-15 19:19:03 +01:00
Windel Bouwman
ca47ddc02c Merge pull request #672 from coolreader18/wasm-vm-exec_single
Use compile::Mode::Single for the demo terminal
2019-03-15 19:10:25 +01:00
Adam Kelly
e8e8544b4b Avoid use of PyObject in objcomplex. 2019-03-15 16:09:04 +00:00
Aviv Palivoda
abb4d41e5b Add selenium test to travis 2019-03-15 17:24:34 +02:00
coolreader18
5b5d3e789a Merge branch 'coolreader18/wasm-remove-hashmap-rcs' 2019-03-15 07:25:43 -05:00
Adam Kelly
871ac15675 Avoid use of PyObject in objbytes. 2019-03-15 12:22:19 +00:00
Adam Kelly
7aa9b94243 Avoid use of PyObject in objbytearray. 2019-03-15 12:21:48 +00:00
Adam Kelly
a0acc7aa6a Avoid use of PyObject in frame.rs. 2019-03-15 12:21:05 +00:00
Adam Kelly
111208b46f Remove PyRef::new/new_with_type. 2019-03-15 11:36:25 +00:00
Aviv Palivoda
f281aab721 Move selenium test to wasm folder 2019-03-15 10:01:10 +02:00
Aviv Palivoda
3d95b70e0f Add selenium test for wasm 2019-03-15 09:13:55 +02:00
Joey
976afeda31 Add helper for obtaining class from module 2019-03-14 23:08:07 -07:00
Joey
fa9e48a5b3 Take &mut VirtualMachine insteadof &PyContext 2019-03-14 21:43:19 -07:00
Joey
737ec12fa5 Rename PyValue::{required_type => class} 2019-03-14 20:08:41 -07:00
coolreader18
a1e0c03a34 Merge pull request #670 from coolreader18/pyvaluepayload
Add PyObjectPayload trait and use it for PyObject.payload
2019-03-14 21:05:55 -05:00
coolreader18
8c1f18157d Remove leftover trace from debugging 2019-03-14 20:41:23 -05:00
coolreader18
f093aa4d6a Merge branch 'master' into pyvaluepayload 2019-03-14 20:25:51 -05:00
coolreader18
d7299bac99 Remove the Rcs around the WASM global HashMaps 2019-03-14 18:13:26 -05:00
coolreader18
2af998ea86 Prevent recursion for Debug impls 2019-03-14 17:54:38 -05:00
Adam
529da3fdfe Merge pull request #678 from RustPython/py_value_into_ref
Py value into ref
2019-03-14 16:22:46 +00:00
Joey
574be4ed3e Merge pull request #674 from RustPython/subclass_str
Fix subclasses of string. (Fixes #130)
2019-03-14 08:54:09 -07:00
Adam Kelly
b204c2b33e Add PyValue::into_ref and into_ref_with_type. 2019-03-14 09:42:40 +00:00
Adam Kelly
5b41cc4b0d Fix subclasses of string. (Fixes #130) 2019-03-14 09:06:29 +00:00
Joey
964a0410e0 Merge pull request #677 from skinny121/property
Implement property attributes and functions
2019-03-13 22:20:10 -07:00
ben
3f301bd684 Implement property attributes and functions 2019-03-14 17:19:43 +13:00
coolreader18
4b655b9ab7 Fix recursive Scope Debug impl 2019-03-13 22:49:09 -05:00
Joey
36204f29fe Merge pull request #676 from adrian17/master
Use Into<BigInt> instead of ToBigInt to avoid copies
2019-03-13 18:54:36 -07:00
Joey
b50ecf1023 Merge pull request #675 from skinny121/property_type_param
Remove type parameter from PropertyBuilder
2019-03-13 18:53:54 -07:00
Adrian Wielgosik
6b1598dbb4 Change some methods to return BigInt directly 2019-03-13 20:21:07 +01:00
Adrian Wielgosik
f647f346f2 Use Into<BigInt> instead of ToBigInt to avoid copies 2019-03-13 20:20:42 +01:00
ben
067fc0927d Remove type parameter from PropertyBuilder 2019-03-14 07:24:49 +13:00
coolreader18
913bb1438a Merge branch 'master' into wasm-vm-exec_single 2019-03-13 08:20:42 -05:00
coolreader18
6436d2cb9c fmt again 2019-03-13 08:16:41 -05:00
Windel Bouwman
c0b7ddfd2c Add write method to io.StringIO 2019-03-13 13:32:57 +01:00
Windel Bouwman
8dcea92bb2 Merge pull request #654 from coolreader18/wasm-explicit-stdout
[WASM] Make setStdout arguments more explicit in what they print to
2019-03-13 12:12:14 +01:00
Windel Bouwman
f0e285d124 Merge pull request #665 from RustPython/type_mro
Type mro
2019-03-13 12:05:59 +01:00
coolreader18
df68acb36b cargo fmt 2019-03-12 23:20:17 -05:00
coolreader18
bde86d32b1 Use compile::Mode::Single for the demo terminal 2019-03-12 22:46:55 -05:00
coolreader18
fb8351c5d1 Inline some functions 2019-03-12 20:59:03 -05:00
coolreader18
7bac1285d4 Fix all the tests 2019-03-12 20:26:33 -05:00
coolreader18
f31003614a Fix wasm 2019-03-12 19:42:52 -05:00
coolreader18
d305d4f74b Clean up a bit 2019-03-12 19:06:12 -05:00
coolreader18
c0e572767e Rename PyValuePayload to PyObjectPayload 2019-03-12 18:59:43 -05:00
coolreader18
070f5aa322 Merge master into pyvaluepayload 2019-03-12 18:36:10 -05:00
coolreader18
e49d7146a0 Add PyValuePayload trait and use it for PyObject.payload 2019-03-12 18:31:59 -05:00
Joey
83788b9d3c Merge pull request #667 from adrian17/no-option-typ
Remove Option from PyObject.typ; Refactor type hierarchy initialization.
2019-03-12 15:59:04 -07:00
Joey
051b382356 Merge pull request #668 from adrian17/compile_opts
Use default opt-level for release builds.
2019-03-12 15:47:20 -07:00
Adrian Wielgosik
a8f7c80e37 Use default opt-level for release builds. 2019-03-12 22:07:24 +01:00
Adrian Wielgosik
b334689e55 Remove Option from PyObject.typ; Refactor type hierarchy initialization. 2019-03-12 21:58:03 +01:00
Windel Bouwman
3cfee902ab Merge pull request #630 from lili668668/dict_get
Implement dict.get
2019-03-12 19:59:25 +01:00
Windel Bouwman
048a9547ce Merge pull request #652 from palaviv/__import__
Add __import__
2019-03-12 19:56:04 +01:00
Adam Kelly
336aa53b13 Allow IdProtocol to compare PyRef and non-PyRef. 2019-03-12 18:44:35 +00:00
Aviv Palivoda
6a3e82efd9 Fix typo 2019-03-12 20:21:59 +02:00
Adam
17082942e4 Merge pull request #666 from RustPython/pyclassref_protocols
Pyclassref protocols
2019-03-12 17:56:25 +00:00
Aviv Palivoda
2c6baacbac Return ImportError __import__ is not in builtins 2019-03-12 19:31:18 +02:00
Aviv Palivoda
e6c460fd97 Add import method to VirtualMachine 2019-03-12 18:35:15 +02:00
Adam Kelly
9f96b16624 Turn PyClass.mro into a Vec<PyClassRef> 2019-03-12 15:09:03 +00:00
Adam Kelly
3082f5faef Trivial implementations of IdProtocol and TypeProtocol for PyClassRef. 2019-03-12 13:43:30 +00:00
Adam Kelly
48fba05e20 Change .__mro__ to read-only attribute so type.__mro__ works. 2019-03-12 11:27:42 +00:00
Adam Kelly
5742e32669 PropertyBuilder: Constraint on setter type is too strong. 2019-03-12 11:27:18 +00:00
Tzu-Yin Hong
de2b928676 Format the code 2019-03-12 11:46:47 +08:00
Joey
a8c02105d1 Merge pull request #662 from adrian17/objint
Convert most objint functions to new args style
2019-03-11 19:39:32 -07:00
Joey
db7d736c68 Merge pull request #661 from RustPython/obj-improvements
Move classmethod and staticmethod to own files. Also use extend_class…
2019-03-11 19:34:35 -07:00
coolreader18
88fff7102e cargo fmt 2019-03-11 20:01:34 -05:00
coolreader18
18f77cee42 Merge branch 'master' into wasm-explicit-stdout 2019-03-11 19:25:13 -05:00
coolreader18
dac75019e5 Remove builtin_print_html, move functionality to JS 2019-03-11 19:18:21 -05:00
Adrian Wielgosik
e3a5ac1378 Make objint::get_value return a reference 2019-03-11 23:07:56 +01:00
Aviv Palivoda
a3823b4540 Test override __import__ 2019-03-11 22:49:55 +02:00
Adam
8ec1af52e8 Merge pull request #660 from RustPython/typetype_clean
Typetype clean
2019-03-11 20:34:26 +00:00
Aviv Palivoda
8c92636a82 Fix wasm code 2019-03-11 22:30:37 +02:00
Aviv Palivoda
87e6d8d13d Add __import__ 2019-03-11 22:29:50 +02:00
Adam Kelly
633a9b0365 Move more methods onto PyClassRef. 2019-03-11 18:58:15 +00:00
Adam Kelly
1e39512e74 Convert _mro to iterator. 2019-03-11 18:58:15 +00:00
Windel Bouwman
3d306fc3e4 Merge pull request #655 from coolreader18/mandelbrot-snippet-generator
Use a generator for the mandelbrot demo snippet
2019-03-11 19:42:17 +01:00
Windel Bouwman
c00d368448 Move classmethod and staticmethod to own files. Also use extend_class more. 2019-03-11 19:38:26 +01:00
Adrian Wielgosik
4cbb1a38f1 Convert most objint functions to new args style 2019-03-11 19:20:22 +01:00
Adam Kelly
3711881a60 Add type_pyref() to TypeProtocol. 2019-03-11 17:42:28 +00:00
coolreader18
482025045f Rearrange mandelbrot.py 2019-03-11 12:17:34 -05:00
coolreader18
31c6df31dc Okay now it works without browser 2019-03-11 12:14:37 -05:00
coolreader18
5ab41f9c54 Make mandelbrot.py work without browser module 2019-03-11 11:59:17 -05:00
Windel Bouwman
caae69fc35 Merge pull request #658 from RustPython/mro
Cleaner type_type declaration, and faster instance checking.
2019-03-11 17:40:09 +01:00
Windel Bouwman
b8aa38db1a Merge pull request #653 from RustPython/joey/pyobject-2.0-prep
Remove PyObjectPayload enum
2019-03-11 17:33:51 +01:00
Adam Kelly
d7e1d69430 Avoid additional clone in objtype::subinstance. 2019-03-11 11:44:25 +00:00
Adam Kelly
4d779bbf98 isinstance/issubclass - avoid expensive construction of full mro. 2019-03-11 11:18:40 +00:00
Adam Kelly
7894627b9d Use extend_class in objtype. 2019-03-11 10:22:53 +00:00
Joey
dfb24d7f11 Merge pull request #657 from skinny121/attribute_error
Use new_attribute_error in more places
2019-03-10 22:13:38 -07:00
ben
65c26a1f1b Use new_attribute_error in more places 2019-03-11 17:38:19 +13:00
Joey
a48340d591 Merge pull request #651 from RustPython/make_module_not_mk_module
Rename mk_module to make_module.
2019-03-10 21:25:31 -07:00
Joey Hain
2449c12bf9 Merge remote-tracking branch 'origin/master' into make_module_not_mk_module
Conflicts:
      vm/src/stdlib/weakref.rs
2019-03-10 20:43:11 -07:00
Joey Hain
053ceb1a30 Move payload boxing into PyObject::new 2019-03-10 20:19:28 -07:00
Joey
cf659b80c0 Merge pull request #656 from adrian17/master
Support index in list.pop()
2019-03-10 17:17:50 -07:00
coolreader18
09ab6d1d7c Reformat 2019-03-10 19:12:48 -05:00
Adrian Wielgosik
b123e58c55 Support index in list.pop() 2019-03-11 00:31:26 +01:00
coolreader18
40ef62db70 Use a generator for the mandelbrot demo snippet 2019-03-10 17:42:39 -05:00
coolreader18
29ec84ead9 Change main.js to print to the console 2019-03-10 17:22:22 -05:00
coolreader18
8407f7498e Change setStdout to take "console" instead of undefined 2019-03-10 17:20:32 -05:00
Joey Hain
4510489bba Fix PyObjectPayload usage in wasm 2019-03-10 15:19:04 -07:00
Joey Hain
5971fc3bd4 rename PyObjectPayload2 to PyValue 2019-03-10 13:48:51 -07:00
Joey Hain
e2e13af7ea Remove PyObjectPayload 2019-03-10 13:45:38 -07:00
Joey Hain
45bc8c8f7a Move PyRef to pyobject module 2019-03-10 13:01:46 -07:00
Joey
8143adc837 Merge pull request #636 from skinny121/weakref_type
Move weakref object type to obj module
2019-03-10 12:57:04 -07:00
Joey Hain
6024e3ea0c Fix irrefutable pattern errors 2019-03-10 12:43:25 -07:00
ben
7c5be7d6b7 Add proper weakref type 2019-03-11 07:49:12 +13:00
Windel Bouwman
ded7acc427 Merge pull request #643 from palaviv/interactive-shell
Add interactive shell to WASM demo
2019-03-10 18:18:41 +01:00
Adam Kelly
0ff5155af9 Rename mk_module to make_module. 2019-03-10 17:10:51 +00:00
Aviv Palivoda
f27cb5b8ed Don't delete prompt 2019-03-10 18:40:03 +02:00
Aviv Palivoda
625e181fd8 Use snakeCase 2019-03-10 18:38:17 +02:00
Aviv Palivoda
264d218b70 Use seperate VM for interactive shell 2019-03-10 18:36:29 +02:00
Windel Bouwman
e8ec497b02 Merge pull request #637 from RustPython/scope_globals_locals
Scope globals locals
2019-03-10 17:13:03 +01:00
Windel Bouwman
1751333686 Merge pull request #650 from chylli/add_str__doc__
add __doc__ to str
2019-03-10 17:08:13 +01:00
Chylli
e38a82e540 add __doc__ to str 2019-03-10 22:39:22 +08:00
Adam Kelly
3fbf627582 Merge branch 'master' into scope_globals_locals 2019-03-10 13:00:03 +00:00
Adam Kelly
4a82c8fad5 Rename AttributeProtocol2 -> NameProtocol with method name changes. 2019-03-10 12:51:34 +00:00
Adam Kelly
15aaa6d3f6 Add builtin_globals. 2019-03-10 12:51:34 +00:00
Adam Kelly
372f09aaa3 Abstract rc linked list so we can just use a loop. 2019-03-10 12:38:43 +00:00
Adam Kelly
ddf4f55af7 Enable tests that now pass thanks to new scope scheme. 2019-03-10 12:38:43 +00:00
Adam Kelly
6ad528c15c Reintroduce new_scope for the common case of an empty scope. 2019-03-10 12:38:43 +00:00
Adam Kelly
0e23e706c9 Restructure scope to distinguish between locals and globals. 2019-03-10 12:38:43 +00:00
Adam
9e5b76c9b6 Merge pull request #635 from skinny121/property_refactor
Unify property like objects
2019-03-10 12:35:24 +00:00
Windel Bouwman
eb19eaa6d6 Merge pull request #646 from RustPython/joey/memoryview-slice
Convert memoryview and slice to Any payload
2019-03-10 10:56:36 +01:00
Joey Hain
f6765cf16e less explicit returns 2019-03-10 00:34:21 -08:00
Windel Bouwman
eb14ada7ad Merge pull request #645 from RustPython/joey/convert-iterator
Convert iterator to Any payload
2019-03-10 09:18:14 +01:00
Windel Bouwman
79b4f62300 Merge pull request #642 from RustPython/joey/function-to-any
Convert function, method, builtin_*, frame, and generator to Any payload
2019-03-10 09:12:20 +01:00
Ryan Liddle
f57d2e22bf Merge pull request #649 from jaroel/context-manager-open
Make IOBase a context manager
2019-03-10 13:41:26 +11:00
Ryan Liddle
6072954024 Merge pull request #647 from RustPython/joey/no-arg-functions
Allow functions that don't take any args
2019-03-10 13:34:53 +11:00
Roel Bruggink
8f6257b37f Make open a context manager 2019-03-10 03:11:28 +01:00
Joey Hain
cd3ca16693 Allow functions that don't take any args 2019-03-09 16:46:29 -08:00
Joey Hain
e1d728e81f slice 2019-03-09 15:10:44 -08:00
Joey Hain
776dd80591 memoryview 2019-03-09 14:58:33 -08:00
Joey
157d18d7a1 Convert iterator 2019-03-09 14:45:55 -08:00
ben
7d01323e09 Merge branch 'master' into property_refactor
# Conflicts:
#	vm/src/function.rs
2019-03-10 09:06:21 +13:00
ben
3c3c1f2b6f Fixed new_attribute_error and added more tests for property 2019-03-10 09:01:46 +13:00
Aviv Palivoda
669aa70aab Support ':' in interactive shell 2019-03-09 21:23:59 +02:00
Aviv Palivoda
03d431ecac Support backspace in interactive shell 2019-03-09 21:17:13 +02:00
Aviv Palivoda
ec3ace527b Change prompt to >>>>> 2019-03-09 20:57:36 +02:00
Joey
6eea40799b generator 2019-03-09 09:28:15 -08:00
Joey
53e4591911 frame 2019-03-09 09:28:12 -08:00
Joey
c1180fc564 builtin_function_or_method 2019-03-09 08:45:46 -08:00
Aviv Palivoda
976c9e8b58 Add interactive shell to WASM demo 2019-03-09 18:41:02 +02:00
Joey Hain
5a74121c76 method 2019-03-09 07:11:28 -08:00
Joey Hain
dd56d1d5a2 function 2019-03-09 07:09:53 -08:00
Joey
010969f2d2 Merge pull request #641 from RustPython/py_module_use
Use py_module at more places.
2019-03-09 07:04:43 -08:00
Joey
1444a1f98c Merge pull request #640 from RustPython/type_annotations2
Add __annotations__ attribute to functions.
2019-03-09 07:04:32 -08:00
Joey
fae776d4ae Merge pull request #638 from adrian17/tuple_list
Convert most tuple/list methods to new args style
2019-03-09 07:04:02 -08:00
Windel Bouwman
6ba5b091e9 Use py_module at more places. 2019-03-09 12:38:14 +01:00
Windel Bouwman
adde4e731f Merge pull request #616 from coolreader18/wasm-syntax-error-location
[WASM] Add row and column info of a syntax error to the JS error
2019-03-09 12:13:23 +01:00
Windel Bouwman
c1ddcbb05f Merge pull request #632 from palaviv/socket-errors
Socket OSError
2019-03-09 11:55:03 +01:00
Windel Bouwman
3f492e5a3f Add __annotations__ attribute to functions. 2019-03-09 11:48:35 +01:00
Aviv Palivoda
8df0e46c32 Try to fix windows CI errors 2019-03-09 09:29:33 +02:00
Adam
56bb6d23cc Merge pull request #634 from RustPython/joey/map-zip-filter-enumerate-to-any
Convert map, zip, filter, and enumerate to Any payload
2019-03-09 06:42:04 +00:00
Adam
3730ca2b43 Merge pull request #551 from coolreader18/store-rcs-in-stored-vm
[WASM] Keep a PyObjectWeakRef to the PyObjectRef being moved to a closure
2019-03-09 06:36:01 +00:00
Adam
9e827cfc9d Merge pull request #631 from RustPython/py_module_payload
Replace PyObjectPayload::Module with PyModule.
2019-03-09 06:33:15 +00:00
Joey Hain
a2951f8a8b enumerate 2019-03-08 18:29:58 -08:00
Joey Hain
9544a47f46 filter 2019-03-08 18:29:57 -08:00
Joey Hain
9d8bdd7012 zip 2019-03-08 18:29:51 -08:00
Joey Hain
303e19d713 map 2019-03-08 18:29:41 -08:00
coolreader18
f1b156dfbf Merge branch 'master' into store-rcs-in-stored-vm 2019-03-08 20:03:13 -06:00
ben
0ec034df51 Change property.__new__ to use new style function and construct
PyProperty
2019-03-09 14:07:42 +13:00
ben
2edfe4c7be Migrate usage of member_descriptor and data_descriptor to
new_property/PropertyBuilder
2019-03-09 13:00:54 +13:00
ben
3fe32d0527 Merge branch 'master' into property_refactor 2019-03-09 12:13:00 +13:00
ben
5abc674737 Change property implementation to have rust payload and to use new
function style.
2019-03-09 12:11:07 +13:00
Adam
9a3b731894 Merge pull request #612 from RustPython/type_annotations2
Compile type annotations on function.
2019-03-08 21:34:40 +00:00
Adrian Wielgosik
10531191bb Convert most tuple/list methods to new args style 2019-03-08 20:43:20 +01:00
Windel Bouwman
8362b8da80 Merge pull request #623 from RustPython/code-of-conduct
Add a code of conduct
2019-03-08 18:53:43 +01:00
Windel Bouwman
502f8098b4 Change returns into return. 2019-03-08 18:51:20 +01:00
Aviv Palivoda
76c43457b5 Add more OSError exceptions to socket 2019-03-08 17:05:05 +02:00
Aviv Palivoda
de0e76baf8 socket connect and bind throws OSError with indicative error message 2019-03-08 16:43:11 +02:00
Aviv Palivoda
3fae8ccfbc Handle unknown socket kind 2019-03-08 16:19:26 +02:00
Aviv Palivoda
40c10ab70a Handle unknown address family 2019-03-08 16:16:59 +02:00
Adam Kelly
3f665ce673 Replace PyObjectPayload::Module with PyModule. 2019-03-08 08:43:07 +00:00
Adam
0febcb9c23 Merge pull request #625 from RustPython/py_class
Add PyClass.
2019-03-08 08:10:35 +00:00
Adam
21382fadbd Merge branch 'master' into py_class 2019-03-08 08:04:23 +00:00
Adam
50de0856ff Merge pull request #627 from RustPython/joey/list-tuple-any
Convert list and tuple to Any payload
2019-03-08 07:22:42 +00:00
Adam
d44129c53c Merge pull request #629 from coolreader18/anyrustvalue-debug
Have AnyRustValue actually format with its own Debug impl
2019-03-08 06:50:55 +00:00
Adam
9b317af586 Merge pull request #628 from coolreader18/objcode-any
Convert CodeObject payload to AnyRustValue
2019-03-08 06:50:26 +00:00
Adam
406ec46ce8 Merge pull request #619 from skinny121/class_property
Fix __class__
2019-03-08 06:47:55 +00:00
Adam
62a2344ba5 Merge pull request #621 from RustPython/pynone
Pynone
2019-03-08 06:47:27 +00:00
Tzu-Yin Hong
cdba098e70 Implement dict.get 2019-03-08 14:41:08 +08:00
Joey
1bcbb28715 Convert list and tuple to Any payload 2019-03-07 21:10:43 -08:00
coolreader18
87a58786af Have AnyRustValue actually format with its own Debug impl 2019-03-07 22:20:10 -06:00
coolreader18
231ab682b9 Convert CodeObject payload to AnyRustValue 2019-03-07 22:18:23 -06:00
ben
4b1cd72355 Add todo for using PyClassRef when that lands 2019-03-08 17:04:32 +13:00
coolreader18
c563a6d498 Convert Python errors to JS errors with row 2019-03-07 20:48:14 -06:00
Joey
3495b04e1a Merge pull request #624 from adrian17/string
Convert most remaining string methods to implicit args
2019-03-07 18:33:12 -08:00
coolreader18
5569f8d322 Merge branch 'master' of git://github.com/RustPython/RustPython into wasm-syntax-error-location 2019-03-07 20:27:11 -06:00
Joey
29e902957e Merge pull request #615 from adrian17/float
Migrate PyFloat to new method style
2019-03-07 12:42:14 -08:00
Adam Kelly
e220f0a571 Add PyClass and remove old Class payload 2019-03-07 20:42:10 +00:00
Adrian Wielgosik
b81a0a16d8 Convert most remaining string methods to implicit args
Also support out-of-range start/end params for some functions.
2019-03-07 20:39:57 +01:00
Windel Bouwman
4b783b1523 Add a code of conduct 2019-03-07 20:00:02 +01:00
Adrian Wielgosik
1601da0692 Migrate PyFloat to new method style 2019-03-07 19:47:16 +01:00
Adam Kelly
995212040a Use PyInstance as the payload rather than (). 2019-03-07 18:42:46 +00:00
Adam Kelly
5b1384814c Move attributes dictionary to PyObject. 2019-03-07 18:04:02 +00:00
Adam Kelly
303f9b95a0 Add (unused) dict element to PyObject struct. 2019-03-07 18:04:02 +00:00
Adam
e0e0734524 Merge pull request #617 from RustPython/joey/int-any
Convert int to Any payload
2019-03-07 18:03:25 +00:00
Adam Kelly
488d9a5922 Merge branch 'master' into joey/int-any 2019-03-07 18:00:59 +00:00
Adam Kelly
adf473faf4 Use macro for NoneType. 2019-03-07 17:06:34 +00:00
Adam Kelly
289c86de67 Add extend_class! macro to neaten definitions of builtins types. 2019-03-07 17:06:11 +00:00
ben
f2f0f1d742 Remove debug statements 2019-03-08 06:03:13 +13:00
Adam Kelly
22811c0d56 Add PyNone and new style definition for NoneType methods. 2019-03-07 17:00:24 +00:00
Adam
ac6521564f Merge pull request #618 from RustPython/joey/optional-arg-2
Improvements to OptionalArg extractor
2019-03-07 08:22:21 +00:00
Adam
cae87f6384 Merge pull request #604 from RustPython/unit-payload
Unit payload
2019-03-07 08:17:43 +00:00
ben
720bec2f4f Convert __class__ descriptor to use new style functions 2019-03-07 20:47:31 +13:00
ben
9d03abf652 Move __class__ attribute to object to make it work in more situations 2019-03-07 20:47:31 +13:00
Joey
f9ab27296a Add conversions for all primitive ints 2019-03-06 20:38:52 -08:00
Joey
4a000c424c Improvements to OptionalArg extractor 2019-03-06 19:53:03 -08:00
Joey
ecc92ffe33 Convert int to Any payload 2019-03-06 19:25:54 -08:00
coolreader18
7b8c8900bc Allow JS errors to get the row and column info of the error 2019-03-06 18:54:57 -06:00
Windel Bouwman
d7f8961a12 Simplify some PyFuncArgs occurences. 2019-03-06 22:30:11 +01:00
Windel Bouwman
eacf2fecc9 Merge pull request #614 from RustPython/__dir__
Dir
2019-03-06 22:14:16 +01:00
Adam Kelly
e0c398cbd5 Eliminate NoPayload and just use a boxed (). 2019-03-06 20:57:03 +00:00
Adam Kelly
d769fa9317 Remove unused function. 2019-03-06 19:08:37 +00:00
Adam Kelly
10bbfc6a34 Implement dir via __dir__. 2019-03-06 19:05:18 +00:00
Adam Kelly
2a593aa100 Add objmodule. 2019-03-06 18:11:52 +00:00
Windel Bouwman
e5ead870bc Merge pull request #605 from RustPython/subscript_list
Add subscript list in grammar.
2019-03-06 17:10:32 +01:00
Windel Bouwman
507a5b698f Merge pull request #611 from RustPython/pyargs
Less explicit PyFuncArgs is better.
2019-03-06 17:10:13 +01:00
Adam Kelly
a72af4d967 Remove None and NotImplemented payloads and replace with NoPayload 2019-03-06 16:04:26 +00:00
Adam Kelly
5afbfafa8b Remove special case for None payload from boolval. 2019-03-06 16:04:26 +00:00
Adam
03b419917e Merge pull request #591 from RustPython/re_module
Re module
2019-03-06 15:57:33 +00:00
Adam
11d0de24c3 Merge pull request #610 from RustPython/joey/impl-on-pyref
Improve readability of methods on PyRef<PyString>
2019-03-06 15:44:55 +00:00
Windel Bouwman
69efc7f223 Compile type annotations on function. 2019-03-06 13:48:30 +01:00
Windel Bouwman
6d84b4d4e9 Less explicit PyFuncArgs is better. implemented a From trait for PyFuncArgs 2019-03-06 12:02:01 +01:00
Windel Bouwman
f3791a3867 Fix test script for python3.6 2019-03-06 11:25:16 +01:00
Ryan Liddle
0000551c0e Merge pull request #608 from palaviv/dict-methods
Add dict.{keys,values,items}
2019-03-06 18:30:30 +11:00
Joey Hain
c68dbcc1ab Improve readability of methods on PyRef<PyString>
- Introduce PyStringRef type alias
- Impl python methods on PyStringRef to allow receiver to just be `self`
2019-03-05 19:56:25 -08:00
Joey
06e17af6cc Merge pull request #607 from adrian17/strings
Convert a bunch of string methods to new-args-style.
2019-03-05 20:50:36 -07:00
Joey
6f61e5847e Merge pull request #603 from RustPython/joey/set-dict-payload
Convert set and dict to Any payload
2019-03-05 20:45:11 -07:00
Joey
c5fca1bb0f Merge pull request #609 from coolreader18/fix-cargo-versions
Fix Cargo.toml versions
2019-03-05 19:41:19 -07:00
Joey Hain
894fa591d0 Merge remote-tracking branch 'origin/master' into joey/set-dict-payload
Conflicts:
      vm/src/pyobject.rs
2019-03-05 18:39:51 -08:00
coolreader18
b5248fbd82 Fix Cargo.toml versions 2019-03-05 17:27:56 -06:00
coolreader18
63613802ca Merge branch 'master' into store-rcs-in-stored-vm 2019-03-05 17:18:43 -06:00
Aviv Palivoda
24dcc06c24 add dict.keys 2019-03-05 22:46:13 +02:00
Aviv Palivoda
475476df71 Add dict.items 2019-03-05 22:41:42 +02:00
Aviv Palivoda
37118c7d75 Add dict.values 2019-03-05 22:34:45 +02:00
Adrian Wielgosik
e4e8b135ef Convert a bunch of string methods to new-args-style.
Mostly skipped the ones dealing with ints.
2019-03-05 20:41:02 +01:00
Windel Bouwman
c1a5e31c3c Extend re module. 2019-03-05 20:24:48 +01:00
Windel Bouwman
6ba25ef1c8 Merge pull request #575 from holygits/fix/bytearray-as-hex
Bytearray hex formatting
2019-03-05 19:58:32 +01:00
Windel Bouwman
0292146a42 Add subscript list in grammar. 2019-03-05 17:28:15 +01:00
Adam
d278fb841c Merge pull request #597 from RustPython/type_hints
Add type annotations to parser.
2019-03-05 14:43:30 +00:00
Ryan Liddle
b7c03b4be5 Merge pull request #601 from RustPython/ellipsis
Add ellipsis syntax.
2019-03-05 18:30:44 +11:00
Windel Bouwman
cb1b9d368f Merge pull request #602 from coolreader18/prep-wasm-npm
Prepare the wasm crate for publishing on npm
2019-03-05 07:25:10 +01:00
Windel Bouwman
81a85cc0bf Merge pull request #599 from palaviv/Fix-locals
Fix locals
2019-03-05 07:23:46 +01:00
Windel Bouwman
458ead0cbc Merge pull request #600 from adrian17/as_ratio
Add float.as_integer_ratio()
2019-03-05 07:22:38 +01:00
Windel Bouwman
883a4944c8 Merge pull request #598 from palaviv/dir-module
Fix module dir
2019-03-05 07:20:12 +01:00
Windel Bouwman
05929b3d7b Add ellipsis type, test and do rustfmt. 2019-03-05 07:19:00 +01:00
holygits
f4ba94a397 Fix formatting 2019-03-05 19:03:25 +13:00
Joey Hain
d9c35f94c2 Convert dict payload 2019-03-04 21:46:21 -08:00
Joey Hain
bf1fe9e5f2 Convert set payload 2019-03-04 21:46:17 -08:00
coolreader18
eefde87594 Cargo.lock update 2019-03-04 21:17:29 -06:00
Joey
006e975bc5 Update wasm/lib/README.md
Co-Authored-By: coolreader18 <33094578+coolreader18@users.noreply.github.com>
2019-03-04 17:16:02 -06:00
coolreader18
55cc653d9b Prepare the wasm crate for publishing on npm 2019-03-04 16:50:30 -06:00
holygits
0584b85d86 Bytearray hex formatting 2019-03-05 10:59:10 +13:00
Windel Bouwman
a26401707f Minor lexer simplifications. 2019-03-04 21:25:35 +01:00
Aviv Palivoda
a545e4392a Test locals indside a function 2019-03-04 22:17:41 +02:00
Windel Bouwman
e25742f184 Add ellipsis syntax. 2019-03-04 21:09:03 +01:00
Windel Bouwman
b50f0be910 Merge pull request #596 from RustPython/joey/complex-to-any
Convert complex to Any payload
2019-03-04 20:55:51 +01:00
Adrian Wielgosik
eed0b3ca45 Add float.as_integer_ratio() 2019-03-04 20:52:56 +01:00
Aviv Palivoda
da57730692 Fix get_locals 2019-03-04 21:52:20 +02:00
Aviv Palivoda
2d31e35844 Add test dir 2019-03-04 21:31:20 +02:00
Windel Bouwman
f7a22254a6 Add return annotation and fix tests in parser. 2019-03-04 20:29:34 +01:00
Aviv Palivoda
d24f79b17d dir show module content 2019-03-04 21:27:03 +02:00
Windel Bouwman
6544f60d9b Add type annotations to parser. 2019-03-04 19:24:34 +01:00
Adam
a7c3f85da7 Merge pull request #595 from palaviv/socket-user-macros
Use py_class and py_module macros in socket
2019-03-04 17:11:08 +00:00
Joey Hain
f820aeb1ea Convert complex payload 2019-03-04 09:04:24 -08:00
Aviv Palivoda
933c8dc792 Use py_module macro 2019-03-04 18:30:37 +02:00
Aviv Palivoda
d2061004a3 Use py_class macro 2019-03-04 18:27:33 +02:00
Windel Bouwman
38c43e0465 Merge pull request #590 from RustPython/exec
Proper construction of scope for exec/eval.
2019-03-04 16:57:12 +01:00
Adam
839f906927 Merge pull request #592 from RustPython/joey/improved-arg-errors
Improve error messages and add docs for new native function machinery
2019-03-04 14:42:18 +00:00
Adam
4ce0a7c216 Merge pull request #586 from RustPython/joey/float-range-any-payload
Convert more objects to `Any` payload
2019-03-04 14:40:06 +00:00
Adam Kelly
c4953ee9ec Remove new macro and inline check into make_scope. 2019-03-04 14:33:53 +00:00
Adam Kelly
0d4887abe6 Fix missing asserts and add (disabled) tests for things that don't work yet. 2019-03-04 14:32:52 +00:00
Adam Kelly
6548c365cb Use check_but_allow_none for exec/eval. 2019-03-04 14:32:52 +00:00
Adam Kelly
4dd0304712 Add check_but_allow_none macro for optional argument checking. 2019-03-04 14:32:52 +00:00
Adam Kelly
c5789a03a3 Proper construction of scope for exec/eval. 2019-03-04 14:32:52 +00:00
Adam
5d28f9bc36 Merge pull request #594 from skinny121/isinstance_2
Only use real isinstance/issubclass for built-ins
2019-03-04 14:31:43 +00:00
ben
b1a070acc2 Only use real isinstance/issubclass for builtins and move the real
versions to the vm.
2019-03-04 19:55:58 +13:00
Joey Hain
2d71f6de28 bytes and bytearray 2019-03-03 20:01:07 -08:00
Joey Hain
4e822ed6cd Improve error messages and add docs for new native function machinery 2019-03-03 12:52:51 -08:00
Windel Bouwman
9b7c0f78c8 Merge pull request #584 from palaviv/socket-udp
Socket UDP
2019-03-03 21:01:15 +01:00
Aviv Palivoda
283b331323 Use vm.ctx.new_tuple 2019-03-03 18:22:20 +02:00
Aviv Palivoda
f09f75ac8d Do implicit bind in socket.sendto 2019-03-03 18:15:14 +02:00
Aviv Palivoda
9b5ba068af Return addr in accept 2019-03-03 18:15:14 +02:00
Aviv Palivoda
86b60faa61 Add socket.{sendto, recvfrom} 2019-03-03 18:15:14 +02:00
Aviv Palivoda
e5d1d11c3e Add UDP to socket 2019-03-03 18:15:14 +02:00
Windel Bouwman
9271115db7 Introduce py_class macro to define classes. (#589)
* Introduce py_class macro to define classes.
* rustfmt
2019-03-03 13:25:00 +00:00
Joey
4f944d33ad Merge pull request #588 from arfan/master
fix typo in README.md, will to with
2019-03-02 19:44:21 -07:00
Abdul Arfan
0a68b7a3da fix typo in README.md, will to with 2019-03-03 09:18:08 +07:00
Joey Hain
e7fb116210 Convert more objects to Any payload 2019-03-02 13:27:00 -08:00
Joey Hain
4558dbf210 Fix build (rustfmt) 2019-03-02 13:25:42 -08:00
Windel Bouwman
b98926a0fb Merge pull request #572 from RustPython/joey/fun-with-functions
Derive types, arity, conversions and more from rust fns
2019-03-02 20:56:52 +01:00
coolreader18
5428154c81 Merge branch 'master' into store-rcs-in-stored-vm 2019-03-02 07:53:48 -06:00
Windel Bouwman
30ddb48037 Use PyResult at more places. 2019-03-02 14:10:46 +01:00
Windel Bouwman
8847081e8b Merge pull request #582 from palaviv/socket-any
Use PyObjectPayload::AnyRustValue for socket
2019-03-02 13:45:48 +01:00
Joey Hain
3478251d40 Merge remote-tracking branch 'origin/master' into joey/fun-with-functions
Conflicts:
      vm/src/lib.rs
      vm/src/pyobject.rs
      wasm/lib/src/vm_class.rs
2019-03-02 04:04:22 -08:00
Joey Hain
a70f251b6a PyNativeFuncFactory => IntoPyNativeFunc 2019-03-02 03:47:37 -08:00
Aviv Palivoda
af2f790d0d Use PyObjectPayload::AnyRustValue for socket 2019-03-02 12:26:23 +02:00
Aviv Palivoda
aed657173f Simplify socket_close 2019-03-02 12:26:23 +02:00
Aviv Palivoda
e4007f530e Add get_socket function 2019-03-02 12:25:59 +02:00
Windel Bouwman
7bb6f8fdaa Minor clippy fix. 2019-03-02 11:22:40 +01:00
Windel Bouwman
8f52e15d32 Minor clippy fixes. 2019-03-02 11:14:35 +01:00
Windel Bouwman
f3e29c8d5f Merge pull request #581 from coolreader18/wasm-example-crate-alert
Use alert() for the WASM example crate
2019-03-02 10:31:40 +01:00
Windel Bouwman
c8afeae0f7 Merge pull request #577 from RustPython/kill_scope_variant
Remove Scope variant from PyObject.
2019-03-02 10:30:41 +01:00
Windel Bouwman
5b39924389 Merge pull request #580 from coolreader18/fix-clippy-lints
Fix a bunch of clippy lints
2019-03-02 10:20:16 +01:00
coolreader18
5f8fb896d7 Fix lints in rustpython_wasm 2019-03-01 20:22:14 -06:00
coolreader18
c99e843769 Fix a clippy lint I missed 2019-03-01 20:13:50 -06:00
coolreader18
58e1533b12 Fix clippy lint for float_is_integer 2019-03-01 20:12:54 -06:00
coolreader18
f364ea5943 Fix a bunch of clippy lints 2019-03-01 18:41:45 -06:00
coolreader18
60603d250e Use alert() for the WASM example crate 2019-03-01 18:06:50 -06:00
Adam Kelly
9d6e9ac889 Move Scope from pyobject to frame. 2019-03-01 20:49:17 +00:00
Adam Kelly
c2e2441388 Remove Scope variant from PyObject. 2019-03-01 20:47:09 +00:00
Joey Hain
e2e3353441 Add factory impl for boxed fn and remove extra constructor 2019-03-01 11:39:52 -08:00
Windel Bouwman
387c21f285 Merge pull request #570 from coolreader18/wasm-vm-inject_module
Add an `injectModule` method to WASMVirtualMachine
2019-03-01 17:16:22 +01:00
Windel Bouwman
e34c8af793 Merge pull request #576 from adrian17/raise-type
Support raising exceptions without call
2019-03-01 17:00:14 +01:00
Adrian Wielgosik
1519426cb4 Support raising exceptions without call 2019-02-28 22:06:14 +01:00
Joey
990c29469a Merge remote-tracking branch 'origin/master' into joey/fun-with-functions
Conflicts:
      vm/src/pyobject.rs
2019-02-28 10:44:46 -08:00
Windel Bouwman
40c1a0f197 Merge pull request #562 from coolreader18/wasm-promise-class
[WASM] Add a Promise class to the browser module
2019-02-28 17:19:41 +01:00
Windel Bouwman
eaaafacd87 Merge pull request #554 from skinny121/isinstance
Call __instancecheck__ and __subclasscheck__
2019-02-28 17:14:12 +01:00
coolreader18
500f48621d Merge branch 'master' into wasm-promise-class 2019-02-28 07:29:17 -06:00
Ryan Liddle
de322689eb Merge pull request #573 from alexpantyukhin/fix_mut_warning
remove redundant mut
2019-02-28 21:07:00 +11:00
Ryan Liddle
f6e99d1e24 Merge pull request #574 from RustPython/fetch_ins
fetch_instruction can just return a reference.
2019-02-28 21:06:18 +11:00
Adam Kelly
786eb2cbfb fetch_instruction can just return a reference. 2019-02-28 08:33:43 +00:00
ben
5779124f11 rustfmt 2019-02-28 20:40:32 +13:00
ben
e30d91febc Swap naming of is{instance, subclass} <-> real_is{instance, subclass} 2019-02-28 20:32:57 +13:00
ben
52c32fab3a Call __instancecheck__ and __subclasscheck__ as part of isinstance and issubclass 2019-02-28 20:30:31 +13:00
Windel Bouwman
b0ee1947c7 Merge pull request #565 from alexpantyukhin/add_kwarg_handling_to_int
add kwarg handling for int
2019-02-28 07:36:08 +01:00
apantykhin
9081cb2b2c remove redundant mut 2019-02-28 06:35:08 +00:00
Windel Bouwman
56e55e87fe Merge pull request #568 from RustPython/framestack_2
Framestack 2
2019-02-28 07:33:04 +01:00
Windel Bouwman
6f2bbd2e4c Merge pull request #545 from palaviv/socket1
Socket improvments
2019-02-28 07:24:10 +01:00
Windel Bouwman
cca19cf71f Merge pull request #569 from coolreader18/wasm-alert
Add alert, confirm, and prompt to the browser module
2019-02-28 07:22:30 +01:00
Joey Hain
67f8c02087 cleanup 2019-02-27 20:05:04 -08:00
Joey Hain
713edc57ee Convert some objstring methods to new style. 2019-02-27 19:53:31 -08:00
Joey Hain
7f75e3ee8a Significant improvements to new function definition style
- PyRef<T> type for accepting references to payloads.
- Args<T> type for consuming remaining positional args
  (mirrors python `*args`).
- KwArgs<T> type for consuming remaining keyword args
  (mirrors python `*kwargs`).
- OptArg<T> type for consuming remaining keyword args
  (no python code equivalent, only possible in native functions like in cpython).
- PyIterable<T> for accepting an iterator over a sequence of Ts.
- Arity checking (but TypeError messages need work)
2019-02-27 19:53:20 -08:00
coolreader18
f6196126e4 Add an injectModule method to WASMVM 2019-02-27 19:25:06 -06:00
coolreader18
ea93fb871c Add alert, confirm, and prompt to the browser module 2019-02-27 17:38:24 -06:00
apantykhin
7e2c702c5e fix fmt 2019-02-27 21:22:24 +00:00
alexpantyukhin
d806a19c23 add kwarg handling for int 2019-02-27 19:58:32 +00:00
Aviv Palivoda
8087ccf274 Add socket.getsockname 2019-02-27 20:47:53 +02:00
coolreader18
e3db472f37 Fix merge conflicts 2019-02-27 12:44:42 -06:00
Adam Kelly
2cc9a606da Avoid double borrow in Frame.nth_value. 2019-02-27 18:23:39 +00:00
Aviv Palivoda
dc0bd73d12 Fix compiler warnings 2019-02-27 20:23:02 +02:00
Aviv Palivoda
4191ba67b3 Copy instead of clone 2019-02-27 20:19:10 +02:00
Aviv Palivoda
716eb4afca Add validation to connect and bind address 2019-02-27 19:54:39 +02:00
Aviv Palivoda
dff6b0be36 Rename sk to socket_kind 2019-02-27 19:54:39 +02:00
Aviv Palivoda
2bdbc40a45 socket.recv read amount of bytes asked 2019-02-27 19:50:31 +02:00
Adam Kelly
676130fc49 Use refcells in frames to solve frame mutability problem. 2019-02-27 10:47:33 +00:00
Adam Kelly
4dd6592aad Keep a stack of frames in the VM. 2019-02-27 10:47:33 +00:00
Windel Bouwman
6c8584cc11 Merge pull request #564 from alexpantyukhin/int_shifts
add overflow errors for int shifts.
2019-02-27 10:55:19 +01:00
alexpantyukhin
70ad78eb21 fix error messages. 2019-02-27 13:22:27 +04:00
Windel Bouwman
9404c7c657 Merge pull request #548 from rickyhan/new_vm_fns
Move set_item to DictProtocol
2019-02-27 09:40:12 +01:00
Windel Bouwman
d5976e2f83 Merge pull request #563 from coolreader18/demo-bits-and-bobs
Quality of life improvements for the demo.
2019-02-27 09:26:46 +01:00
Windel Bouwman
9a36951428 Merge pull request #559 from adrian17/list_sort
Add list.sort, sorted()
2019-02-27 09:24:22 +01:00
Windel Bouwman
28d5acc25c Merge pull request #552 from AaronRocinante/lexer_handle_random_byte
add lexer error
2019-02-27 08:13:19 +01:00
alexpantyukhin
15e6187583 add overflow errors for int shifts. 2019-02-27 11:11:38 +04:00
Windel Bouwman
f8e96394b7 Merge pull request #561 from rickyhan/rustfmt
Rustfmt
2019-02-27 08:11:33 +01:00
coolreader18
179304bc93 Update WASM example crate/app 2019-02-26 23:48:23 -06:00
coolreader18
c4513a176b Proper error handling for int to animationFrame id 2019-02-26 22:20:28 -06:00
coolreader18
b82e829c1f newline 2019-02-26 21:27:30 -06:00
coolreader18
717392c3c5 Scroll to the bottom of the demo when it gets updated 2019-02-26 21:21:43 -06:00
coolreader18
3df8f1c788 Update the snippet on page load; insert spaces when tab is pressed 2019-02-26 20:55:23 -06:00
coolreader18
1d193e7fc7 Convert between JS Promises and PyPromises 2019-02-26 20:37:59 -06:00
coolreader18
ba1c5d78aa Add a Promise class to the browser module 2019-02-26 20:28:25 -06:00
ricky han
21ebb03242 rust fmt 2019-02-26 18:38:16 -05:00
ricky han
ec93c55e6d rustfmt 2019-02-26 18:37:40 -05:00
ricky han
233f5d42fb Merge branch 'rustfmt' into new_vm_fns 2019-02-26 18:33:58 -05:00
ricky han
d5f0e25686 add rustfmt.toml 2019-02-26 18:32:27 -05:00
ricky han
30145ec6e2 cargo fmt 2019-02-26 17:47:03 -05:00
ricky han
830cc7e990 revert macro 2019-02-26 17:46:06 -05:00
ricky han
0a2aa1e64b fix compile 2019-02-26 17:39:56 -05:00
Ricky Han
0722487d16 Merge pull request #1 from RustPython/master
upstream
2019-02-26 17:21:57 -05:00
Windel Bouwman
d6242ac6e3 Use py_module macro on ast module. 2019-02-26 22:27:59 +01:00
Adrian Wielgosik
45da6b8af1 Add list.sort, sorted() 2019-02-26 22:03:45 +01:00
Aaron
267934bb49 fmt 2019-02-26 12:50:18 -08:00
Windel Bouwman
f2e60b24e1 Add initial platform module. 2019-02-26 21:42:38 +01:00
Windel Bouwman
a6341d3ec8 Merge pull request #558 from silmeth/io-import
fix io module being initialized multiple times
2019-02-26 21:03:47 +01:00
silmeth
5949a9bd13 fix io module being imported multiple times 2019-02-26 20:23:43 +01:00
Windel Bouwman
c33abe91e9 Use py_module macro at more places. 2019-02-26 19:53:58 +01:00
Windel Bouwman
2fc53a9440 Merge pull request #539 from coolreader18/wasm-browser-req_anim_frame
[WASM] Add requestAnimationFrame to browser module
2019-02-26 19:28:18 +01:00
Windel Bouwman
aa48718d0a Merge pull request #549 from coolreader18/rust-value-payload
Add AnyRustValue payload variant
2019-02-26 17:26:44 +01:00
Windel Bouwman
82e2ba19ab Merge pull request #550 from coolreader18/remove-console_error-crate
Remove the console_error_panic_hook crate from Cargo.toml
2019-02-26 17:23:55 +01:00
Windel Bouwman
53f54e4d76 Merge pull request #546 from rickyhan/master
Use closure instead of function pointer for StdlibInitFunc
2019-02-26 17:21:59 +01:00
Windel Bouwman
f8b9d19ccc Merge pull request #553 from RustPython/joey/refcell-in-payload
Remove outer RefCell from PyObjectRef
2019-02-26 17:18:59 +01:00
Windel Bouwman
c3309ee867 Merge pull request #555 from RustPython/dis_dis
Dis dis
2019-02-26 17:07:41 +01:00
Ricky Han
53eff6c9d7 revert 2019-02-26 05:11:38 -05:00
Adam Kelly
73a65a1c77 dis.rs - small refactor dis_dis. 2019-02-26 09:41:39 +00:00
Adam Kelly
79f43ad762 Add support for pulling __code__ out of a function (and a test that hits lots of instructions). 2019-02-26 09:41:39 +00:00
Adam Kelly
2c0016a171 Minimal definition of dis.dis. 2019-02-26 09:41:39 +00:00
Aaron
b1088c629c fmt 2019-02-26 00:55:16 -08:00
Joey Hain
b8eb4c38e8 Fix wasm 2019-02-25 23:10:06 -08:00
Joey Hain
bd3630260a fix socket 2019-02-25 22:22:45 -08:00
Joey Hain
3dcbc4d2aa Fix set 2019-02-25 22:20:15 -08:00
Ricky Han
138de0dfcd fix build error 2019-02-26 01:15:41 -05:00
Ricky Han
baf3fe4bec fix build error 2019-02-26 01:15:09 -05:00
Joey Hain
92fd12c9bd Fix scope 2019-02-25 22:07:08 -08:00
Joey Hain
d3646925ea Fix float() 2019-02-25 21:57:37 -08:00
Joey Hain
b28b164d75 Fix generators 2019-02-25 21:35:59 -08:00
Ricky Han
432b9dffaf cargo fmt 2019-02-26 00:34:40 -05:00
Ricky Han
93a6b4fef9 reverse kwargs order 2019-02-26 00:32:19 -05:00
Joey
587f871396 Merge pull request #542 from AaronRocinante/invalid_control_ret_yield
fix invalid break continue return yield
2019-02-25 21:28:17 -08:00
Joey Hain
e959908a49 Fix iterator 2019-02-25 21:26:15 -08:00
Aaron
b0bf93e530 add lexer error 2019-02-25 21:13:18 -08:00
Ricky Han
3fc583813a fix macro 2019-02-26 00:05:41 -05:00
Joey Hain
f10fa6db44 Remove outer RefCell from PyObjectRef 2019-02-25 21:01:37 -08:00
Ricky Han
88028dd8c5 cargo fmt 2019-02-25 23:41:17 -05:00
Ricky Han
b1c97ec877 refactor macros 2019-02-25 23:36:32 -05:00
Aaron
fee6a47d88 rever new_label() 2019-02-25 20:35:43 -08:00
Aaron
f037244641 fmt 2019-02-25 20:33:03 -08:00
Aaron
f965c49704 compiler flag in_function_def 2019-02-25 20:31:03 -08:00
coolreader18
88665e9ebd Keep a Weak to the py_obj being moved to a closure 2019-02-25 22:27:43 -06:00
coolreader18
d399faa425 Remove the console_error_panic_hook crate from Cargo.toml 2019-02-25 20:50:53 -06:00
coolreader18
dbfd0d4ade Fix "not all variants covered" error 2019-02-25 20:05:41 -06:00
coolreader18
dfa5e12b3c Add AnyRustValue payload variant 2019-02-25 19:22:16 -06:00
coolreader18
9066c73814 Try to trigger a successful Azure Pipelines build 2019-02-25 19:09:26 -06:00
Ricky Han
6f85a44f7c cargo fmt 2019-02-25 16:35:19 -05:00
Ricky Han
6752f67292 cargo fmt 2019-02-25 16:34:55 -05:00
Ricky Han
cf400501a1 move set_item to DictProtocol 2019-02-25 16:32:50 -05:00
Ricky Han
943ded07bd fix wasm 2019-02-25 15:23:40 -05:00
Ricky Han
293ffc072c merge upstream 2019-02-25 14:54:10 -05:00
Ricky Han
985e35bb16 use closure instead of function pointer 2019-02-25 14:49:20 -05:00
Aaron
4a7d2cb010 reset in_loop in class definition block 2019-02-25 09:42:02 -08:00
Aaron
2f0f1b0913 use boolean flag 2019-02-25 09:32:58 -08:00
Aaron
7610d44865 cargo fmt 2019-02-25 00:26:06 -08:00
Aaron
e9b0454f1c fix invalid break continue return yield 2019-02-25 00:12:15 -08:00
Windel Bouwman
027a6847e5 Merge pull request #525 from RustPython/joey/extractor-pattern
Use "extractor" pattern for native functions
2019-02-25 07:22:00 +01:00
Windel Bouwman
9e03b6908c Merge pull request #538 from RustPython/joey/f-string-conversion-flags
Support f-string conversion flags
2019-02-25 07:21:09 +01:00
Windel Bouwman
22928be01a Merge pull request #537 from coolreader18/wasm-fix-select
[WASM] Fix snippet selector's default selection
2019-02-25 07:14:01 +01:00
Windel Bouwman
2d1b45162d Merge pull request #529 from palaviv/socket
socket module
2019-02-25 07:11:32 +01:00
Joey Hain
f050acba73 f-strings: allow ':' and '!' to be used in the expression 2019-02-24 21:13:08 -08:00
coolreader18
1646b53c72 Add a comment explaining the weird dict 2019-02-24 21:28:25 -06:00
coolreader18
5dd2de0b1e Add requestAnimationFrame to browser module 2019-02-24 21:13:51 -06:00
Joey Hain
ddc154a1dd f-strings: support conversion flags 2019-02-24 14:37:59 -08:00
Joey Hain
d6e317b185 Move f-string parser into own module and clean up a bit 2019-02-24 13:01:25 -08:00
coolreader18
f2079807bd Fix snippet selector's default selection 2019-02-24 14:22:18 -06:00
Aviv Palivoda
c87cf90043 Add socket test 2019-02-24 22:20:20 +02:00
Aviv Palivoda
1322c8d6db Change socket parameters to match CPython 2019-02-24 22:20:07 +02:00
Aviv Palivoda
c84d35126e Add socket.{bind,listen,accept} 2019-02-24 21:35:47 +02:00
Aviv Palivoda
49837f57a7 Use Connection enum 2019-02-24 20:43:24 +02:00
Aviv Palivoda
8186c77eb2 Initial socket module 2019-02-24 20:43:24 +02:00
Joey
205bfb762d Merge pull request #532 from coolreader18/wasm-better-panic
[WASM] Make panic errors available from JS
2019-02-24 10:05:20 -08:00
coolreader18
9a7bb315e2 Merge branch 'master' into wasm-better-panic 2019-02-24 09:09:09 -06:00
Windel Bouwman
098675dfe1 Merge pull request #531 from coolreader18/wasm-fetch-builtin
[WASM] Add a `browser` module
2019-02-24 11:13:40 +01:00
Joey
cbcf7c3e75 Merge pull request #534 from AdamGS/new_float_attributes
Addred real property and is_integer function to float.
2019-02-23 22:19:37 -08:00
Joey Hain
2919d7f520 Initial arg type checking 2019-02-23 19:27:22 -08:00
Joey Hain
fb0384d24d Some prerequisite data types for arg checking 2019-02-23 18:16:24 -08:00
Joey Hain
a74cbbbe19 Impl PyNativeFuncFactory for up to 5-tuples 2019-02-23 18:16:18 -08:00
Joey Hain
c14a8302e8 Initial prototype of "extractor pattern" for native funcs 2019-02-23 18:16:02 -08:00
Adam Gutglick
f4e6e5dec8 Addred real property and is_integer function to float. 2019-02-24 04:02:24 +02:00
coolreader18
9d99f94a3f Add! 2019-02-23 16:21:10 -06:00
coolreader18
2b9adfea8a Add fetch demo snippet 2019-02-23 15:25:12 -06:00
coolreader18
7f626b50b9 Merge branch 'master' into wasm-fetch-builtin 2019-02-23 15:20:59 -06:00
Windel Bouwman
d44f1b3e29 Merge pull request #528 from coolreader18/multiple-demo-snippets
Allow for different demo snippets to be selected
2019-02-23 22:15:00 +01:00
coolreader18
ff66bb602e Follow clippy's advice 2019-02-23 15:05:52 -06:00
coolreader18
878c131af4 Make panic errors available and display them nicely for the demo 2019-02-23 14:52:02 -06:00
coolreader18
fd184a1e68 Add a WASM browser module with fetch() available 2019-02-23 13:58:19 -06:00
coolreader18
5a472e46aa Merge branch 'master' into wasm-fetch-builtin 2019-02-23 12:28:17 -06:00
coolreader18
6e8b88e1fd Add mandelbrot snippet 2019-02-23 11:05:51 -06:00
coolreader18
b89d95c4c6 Add fizzbuzz demo 2019-02-23 10:50:07 -06:00
coolreader18
4dde810e9c Move snippets directory 2019-02-23 10:22:36 -06:00
coolreader18
d02e8352ea Allow for multiple demo snippets to be selected 2019-02-23 09:17:00 -06:00
Windel Bouwman
c675a59288 Merge pull request #526 from palaviv/assertRaises
Add assertRaises context manager to testutils
2019-02-23 13:35:19 +01:00
Aviv Palivoda
b530733c1a Add assertRaises context manager to testutils 2019-02-23 13:11:26 +02:00
Windel Bouwman
7032de96d7 Merge pull request #311 from nhynes/compile-wasm
Allow compiling VM for wasm32-unknown-unknown
2019-02-23 10:42:09 +01:00
Windel Bouwman
b15ade1130 Merge pull request #267 from coolreader18/wasm-vm-class
Add a VirtualMachine class to the WASM library
2019-02-23 10:36:23 +01:00
Windel Bouwman
3f8f0e2ff4 Merge pull request #524 from palaviv/Improve-set-5
Add set.{__iter__,__ior__,__iand__,__isub__,__ixor__}
2019-02-23 08:50:26 +01:00
coolreader18
e0f222cf4f Don't hold on to a PyObjectRef from a python -> js closure 2019-02-23 00:20:15 -06:00
coolreader18
09e2a7a493 Add js_name for .set_stdout() 2019-02-23 00:02:12 -06:00
coolreader18
7fa0a0cee3 Fix open in new make_module 2019-02-22 22:59:15 -06:00
coolreader18
955d0b3a91 Merge branch 'master' into wasm-vm-class 2019-02-22 22:53:34 -06:00
coolreader18
65857e7261 Merge 2019-02-22 22:20:05 -06:00
Windel Bouwman
2d19486192 Merge pull request #520 from RustPython/py_module
Py module
2019-02-22 17:20:27 +01:00
Joey
2df741452b Merge pull request #523 from AdamGS/complex_and_ints_addition
Complex and ints addition
2019-02-22 07:34:47 -08:00
Aviv Palivoda
fc10560308 Add set.{__ior__,__iand__,__isub__,__ixor__} 2019-02-22 16:50:40 +02:00
Aviv Palivoda
7cf25440fa Add set.__iter__ 2019-02-22 16:25:55 +02:00
Adam Gutglick
f333c75fd6 Added the ability to do addition between complex numbers and ints. 2019-02-22 08:42:44 -05:00
coolreader18
9e176902b9 Use crate:: imports 2019-02-21 23:25:05 -06:00
Joey
c22fb58437 Merge pull request #521 from chapeupreto/patch-1
fix typos
2019-02-21 19:06:47 -08:00
Rod Elias
b518867220 fix typos 2019-02-21 23:41:43 -03:00
Adam Gutglick
38b4c10833 Added the ability to do addition between complex numbers and ints. 2019-02-21 19:28:46 -05:00
Joey
8f37b9f443 Merge pull request #519 from AdamGS/testutil_back_comp
Backwards compitability for python 3.5 to run tests.
2019-02-21 14:31:03 -08:00
Adam Kelly
0cbcc70359 builtins - use py_module. 2019-02-21 21:14:08 +00:00
Adam Kelly
2ab90b234a Fix unused variable warning in objint. 2019-02-21 21:05:46 +00:00
Adam Kelly
2c97a50e6e sys - use py_module. 2019-02-21 21:05:00 +00:00
Adam Kelly
d420c7f400 dis - use py_module. 2019-02-21 21:04:42 +00:00
Adam Gutglick
999ca431d5 Fixed typo. 2019-02-21 16:03:07 -05:00
Adam Gutglick
365680c272 Changed to syntax RustPython supports. 2019-02-21 15:55:18 -05:00
Windel Bouwman
7dd1eec936 Merge pull request #517 from palaviv/set-more-funcs
Add set.{pop,update,intersection_update,difference_update,symmetric_difference_update}
2019-02-21 20:53:41 +01:00
Windel Bouwman
565023f55b Merge pull request #518 from AdamGS/add_int_attributes
Added real/imag attributes to int type.
2019-02-21 20:52:06 +01:00
Windel Bouwman
5bd2db817f Merge pull request #516 from RustPython/joey/argcheck-objtype
Don't require objtype import to use arg_check! macro
2019-02-21 20:49:14 +01:00
Adam Gutglick
81a9e6984d Changed syntax in testutils.py that is introduced in 3.6 to a backwards compatible version. 2019-02-21 14:47:36 -05:00
Windel Bouwman
2c1afc4ef0 Merge pull request #513 from RustPython/py_module_macro
Py module macro
2019-02-21 20:47:35 +01:00
Windel Bouwman
1d3db316da Merge pull request #512 from RustPython/mod_dis
Mod dis
2019-02-21 20:44:27 +01:00
Windel Bouwman
7dfd8f0ebc Merge pull request #515 from RustPython/joey/compile-error-cleanup
Compile error message cleanup
2019-02-21 20:41:01 +01:00
Adam Gutglick
852dd1086a Added tests to imag/real attributes. 2019-02-21 14:11:23 -05:00
Adam Gutglick
0c1057f079 Added real/imag attributes to int type. 2019-02-21 13:46:18 -05:00
Aviv Palivoda
21b6616e8e Add set.symmetric_difference_update 2019-02-21 19:33:20 +02:00
Aviv Palivoda
1621d78326 Add set.difference_update 2019-02-21 19:02:05 +02:00
Aviv Palivoda
a4b814e9a7 Add set.intersection_update 2019-02-21 18:55:22 +02:00
Joey
eec76ef8e8 Don't require objtype import to use arg_check! macro 2019-02-21 08:38:02 -08:00
Aviv Palivoda
5f3664e87d Add set.update 2019-02-21 18:34:47 +02:00
Aviv Palivoda
a89b0593da Add set.pop 2019-02-21 18:34:47 +02:00
Joey
7e40b7f648 Compile error message cleanup 2019-02-21 08:27:35 -08:00
Adam
e2ee933256 Merge pull request #514 from RustPython/joey/crate-imports
Replace most relative imports with 2018-style crate imports
2019-02-21 15:29:38 +00:00
Adam Kelly
55148d7d5a Use py_module for random. 2019-02-21 14:06:57 +00:00
Adam Kelly
727b895930 Use py_module for math. 2019-02-21 14:06:57 +00:00
Adam Kelly
0175780cc3 py_module macro to make modules definitions more declarative. 2019-02-21 14:06:57 +00:00
Adam Kelly
5ebfd55b20 Add extremely minimal dis module. 2019-02-21 14:02:59 +00:00
Adam Kelly
4b03e6d706 Add Display implementation for CodeObject. 2019-02-21 14:02:59 +00:00
coolreader18
8c222af65b Include details about thread_local! for WASM 2019-02-20 22:33:52 -06:00
Joey
dc3a44f513 Merge pull request #502 from janczer/add_bytearray_lower_upper
Add bytearray.{lower, upper}
2019-02-20 15:49:50 -08:00
janczer
b833c08951 Add bytearray.{lower, upper} 2019-02-20 19:35:39 +01:00
Joey
df76ffe116 Replace most relative imports with 2018-style crate 2019-02-20 08:50:53 -08:00
Windel Bouwman
e058179b04 Merge pull request #458 from ZapAnton/2018_edition
Migrated the project to the Rust 2018 edition
2019-02-20 16:44:31 +01:00
Windel Bouwman
a2ff87b9d7 Merge pull request #506 from janczer/add_check_byte_value
Add checking if value more then 255 in bytearraya
2019-02-20 16:14:09 +01:00
Windel Bouwman
b7dfbebd2d Merge pull request #500 from crw5996/break-continue-fix
Break continue fix
2019-02-20 16:12:57 +01:00
Windel Bouwman
32daf638dc Merge pull request #507 from rmliddle/develop
Readme Update + Inheritance Fix on IO
2019-02-20 16:05:39 +01:00
Joey
b8cb9f73c5 Merge branch 'master' into add_check_byte_value 2019-02-20 06:40:58 -08:00
Joey
f588f58dd1 Merge pull request #503 from janczer/add_pop_bytearray
Add pop to bytearray
2019-02-20 06:33:10 -08:00
rmliddle
6be7623a94 Spelling Fix 2019-02-20 21:36:56 +11:00
Ryan Liddle
3bb00fa5db Merge pull request #505 from RustPython/fix-continue
Fix continue statement
2019-02-20 21:10:45 +11:00
rmliddle
2ad4dddd16 README Update 2019-02-20 21:00:50 +11:00
janczer
51f6ec2325 Add checking if value more then 255 in bytearraya 2019-02-20 07:10:42 +01:00
janczer
24176f7bbb Add more test for bytearray.pop and fix the panic message 2019-02-20 06:58:43 +01:00
janczer
bfdb82b5c1 Add pop to bytearray 2019-02-20 06:50:33 +01:00
Joey
9face190ab Fix continue statement 2019-02-19 19:40:34 -08:00
Joey
53bcd04f8a Merge pull request #499 from RustPython/break-from-nested-for-loops
Fix infinite loop when breaking from nested for loop
2019-02-19 18:33:11 -08:00
Joey
7c06cedf48 Merge pull request #504 from palaviv/fix-key-error
Add KeyError to builtins
2019-02-19 18:24:00 -08:00
chris
9092d1f30b Updated to fix corner case with inner function 2019-02-19 21:11:50 -05:00
chris
d3280429db Merge branch 'break-continue-fix' of https://github.com/crw5996/RustPython into break-continue-fix 2019-02-19 21:03:15 -05:00
chris
5b86b918f1 q!
Merge branch 'master' of https://github.com/RustPython/RustPython into break-continue-fix
2019-02-19 20:47:49 -05:00
coolreader18
8e5073e524 Convert bytes and bytearrays to Uint8Arrays 2019-02-19 17:58:57 -06:00
Joey
cd8c1efb6b Merge pull request #494 from janczer/add_clear_dict_bytes
Add dict.clear and bytes.clear
2019-02-19 15:46:32 -08:00
Chris Wood
a451e4a5b3 Hopefully fixed rustfmt issues 2019-02-19 14:48:23 -05:00
Aviv Palivoda
218cec98cb Add KeyError to builtins 2019-02-19 21:38:39 +02:00
janczer
2963dd5b66 Change error to panic in bytearray.clear 2019-02-19 20:38:38 +01:00
Windel Bouwman
ac95b61e3e Merge pull request #496 from adrian17/arg_check_comments
Document arg_check! macro a bit
2019-02-19 17:42:47 +01:00
rmliddle
724d9c6dcb Fixed Inheritance on String & BytesIO to reflect CPython 2019-02-19 20:41:43 +11:00
chris
6229efca24 Updated Compilation phase to detect whether or not we are currently inside of a loop or not. This is useful to determine whether or not we can use looping specific keywords such as break or continue. 2019-02-19 02:19:14 -05:00
chris
0cc898e19d Updated Compilation phase to detect whether or not we are currently inside of a loop or not. This is useful to determine whether or not we can use looping specific keywords such as break or continue. 2019-02-19 02:18:52 -05:00
janczer
d5c91a8de0 Move clear method from bytes to bytearray 2019-02-19 07:11:13 +01:00
Joey Hain
7965a63ba9 Fix infinite loop when breaking from nested for loop 2019-02-18 18:07:35 -08:00
coolreader18
d716313283 Add content_type option to headers 2019-02-18 15:54:06 -06:00
coolreader18
92a3733541 Add body option to fetch 2019-02-18 15:38:12 -06:00
coolreader18
4edca2121d Convert some fetch options to kwargs, add PyFuncArgs method 2019-02-18 15:25:52 -06:00
Adrian Wielgosik
e016b68552 Document arg_check! macro a bit 2019-02-18 19:59:28 +01:00
coolreader18
9c0bcc2bd7 Re-add WASM fetch builtin 2019-02-18 12:18:53 -06:00
coolreader18
634571fd2e Remove WASM fetch builtin 2019-02-18 12:16:43 -06:00
janczer
58369b6fbc Delete unnessesary code from dict.clear 2019-02-18 18:45:49 +01:00
janczer
85110f6fbf Add dict.clear and bytes.clear 2019-02-18 18:21:39 +01:00
Windel Bouwman
fcea8455fa Merge pull request #473 from janczer/add_list_copy
Add copy method to set object
2019-02-18 10:50:20 +01:00
Windel Bouwman
16832c8f8c Merge pull request #479 from calixteman/fix_equality
Fix issue with equality
2019-02-18 10:49:36 +01:00
Windel Bouwman
43d9fc5dc0 Merge branch 'master' into fix_equality 2019-02-18 08:12:12 +01:00
Windel Bouwman
a47e979f29 Merge branch 'master' into add_list_copy 2019-02-18 08:08:31 +01:00
Windel Bouwman
70d5cdbe3e Merge pull request #492 from OddCoincidence/inplace-ops
Support magic methods for in-place operations
2019-02-18 08:05:59 +01:00
Windel Bouwman
71f32ee9b0 Merge pull request #491 from calixteman/fix_ccov_badge
Fix typo in codecov.io badge
2019-02-18 07:58:32 +01:00
coolreader18
0d3d09072e Convert pyEval to use a WASM VM, allowing closures and stuff
Like variables carried across executions
2019-02-18 00:37:00 -06:00
Joey Hain
ddc7da4a9d Add test for in-place ops 2019-02-17 18:17:26 -08:00
Joey Hain
afabde26d5 coverage: try deleting old gcda files 2019-02-17 17:18:47 -08:00
coolreader18
101ee77dcc Improve error messages 2019-02-17 18:25:14 -06:00
coolreader18
74e713197a Clean up some code 2019-02-17 18:22:11 -06:00
Joey Hain
7abaea556a Micro-optimize list.__iadd__ 2019-02-17 14:30:38 -08:00
coolreader18
524470789f Add eval() method, rename run() to exec() 2019-02-17 13:19:19 -06:00
Joey Hain
dcb29ab1f0 Add list.__iadd__ 2019-02-17 10:54:25 -08:00
Joey Hain
b310d5e24b Use i-methods for in-place operations 2019-02-17 10:47:58 -08:00
coolreader18
bead3f67d0 Fix conversion from ArrayBuffer, allow array_buffer in fetch 2019-02-17 11:50:05 -06:00
Joey Hain
fe3f45f655 Implement remaining binop reverse fallbacks 2019-02-17 09:26:31 -08:00
coolreader18
416f088b32 Convert ArrayBuffers and TypedArrays to Python bytearrays 2019-02-17 11:22:29 -06:00
Calixte Denizet
b61730972e Fix typo in codecov.io badge 2019-02-17 17:07:49 +01:00
coolreader18
b043f2199f Fix js_py_typeerror 2019-02-17 09:14:06 -06:00
coolreader18
7405c842c8 Add some more options to fetch() 2019-02-17 08:49:19 -06:00
coolreader18
d0b4751ab2 Remove the VM pointer from the map when it's dropped 2019-02-17 08:08:22 -06:00
coolreader18
00bc9e9199 Convert fetch to use wasm_bindgen_futures 2019-02-17 01:12:38 -06:00
Windel Bouwman
1af9cc0173 Merge pull request #489 from OddCoincidence/decorator-paths
Allow attributes to be used as decorators
2019-02-17 08:01:25 +01:00
Windel Bouwman
cb2a807994 Merge pull request #486 from OddCoincidence/assert-raises
Reuse and improve ergonomics of assert_raises utility
2019-02-17 07:59:34 +01:00
Windel Bouwman
9d218bf806 Merge pull request #485 from calixteman/ccov
Code coverage for RustPython
2019-02-17 07:56:58 +01:00
Windel Bouwman
a92f4bbecc Merge pull request #487 from liranringel/azure-pipelines
Add Windows CI via Azure Pipelines
2019-02-17 07:54:31 +01:00
coolreader18
f00c3c8a7b Fix fetch builtin 2019-02-17 00:24:58 -06:00
coolreader18
a86069d9f2 Store the WASM id in the VirtualMachine, add a (broken) fetch builtin 2019-02-16 23:41:41 -06:00
coolreader18
3e22c4f146 Add print to default vm scope 2019-02-16 21:43:51 -06:00
Joey Hain
114d9df1d1 Allow attributes to be used as decorators 2019-02-16 19:43:25 -08:00
coolreader18
c83ff47f3a Fix error with new compile() and set_attr/item() 2019-02-16 21:31:10 -06:00
coolreader18
f55a8ead68 Merge branch 'master' into wasm-vm-class 2019-02-16 20:23:35 -06:00
coolreader18
6851767654 Fix RefCell borrowing errors 2019-02-16 20:18:27 -06:00
Calixte Denizet
6d646cc38e Add a codecov badge 2019-02-16 18:33:45 +01:00
Joey Hain
47e95486f0 Reuse and improve ergonomics of assert_raises utility
- Move assert_raises to testutils
- Add optional message argument, with reasonable default
- Reverse order of expr and exception type for readability
- Lambda argument no longer takes parameter
- Convert applicable snippets to use assert_raises
2019-02-16 09:32:42 -08:00
Liran Ringel
9b7160800b Fix os_info.py to pass on windows 2019-02-16 19:23:33 +02:00
Calixte Denizet
e86e108e67 Don't run tests in --release with code coverage 2019-02-16 18:19:52 +01:00
Liran Ringel
2554174697 Set up CI with Azure Pipelines 2019-02-16 18:34:45 +02:00
Calixte Denizet
31c5b5ed3d Workaround issue with grcov 2019-02-16 17:30:05 +01:00
Calixte Denizet
ce541a1ca5 Remove parenthesis 2019-02-16 15:55:41 +01:00
Calixte Denizet
1e3c2fbf18 Try again 2019-02-16 15:28:43 +01:00
Calixte Denizet
90184bcb90 Code coverage for RustPython 2019-02-16 14:54:29 +01:00
Calixte Denizet
5a154f9745 Fix list & tuple equality 2019-02-16 14:23:20 +01:00
Calixte Denizet
93c184a745 Fix fmt 2019-02-16 13:25:13 +01:00
Calixte Denizet
dd6b5b9aae Fix list_eq 2019-02-16 13:15:58 +01:00
Calixte Denizet
117c6c8494 Fix list_remove 2019-02-16 13:00:39 +01:00
Calixte Denizet
5d82e2c6b5 Fix equality check in list_count, list_index and list_contains 2019-02-16 12:45:57 +01:00
Calixte Denizet
bf19d652dc Fix issue with equality 2019-02-16 12:45:57 +01:00
Windel Bouwman
159daf061a Change scope from using set_item to set_attr. 2019-02-16 11:18:55 +01:00
Windel Bouwman
163a1311f7 Merge pull request #470 from janczer/add_remove_list
Add remvoe to list object
2019-02-16 10:27:27 +01:00
Windel Bouwman
26f9a7fe1a Merge pull request #483 from OddCoincidence/f-string-format-specs
Support format specs in f-strings
2019-02-16 08:35:21 +01:00
Windel Bouwman
eb55d20b4a Merge pull request #480 from janczer/fix_clippy_issues
Remove return, use function without closure
2019-02-16 08:31:26 +01:00
Windel Bouwman
ec6dc7ca4a Merge pull request #481 from evilpie/discard
implement set.discard
2019-02-16 08:30:57 +01:00
Windel Bouwman
0a70852b3f Merge pull request #478 from silmeth/int-division
big Integers division
2019-02-16 08:22:29 +01:00
Joey Hain
134c3b94a5 support format specs in f-strings 2019-02-15 18:18:44 -08:00
Joey Hain
5968c4d922 convert f-string parser to state machine 2019-02-15 18:14:33 -08:00
Ryan Liddle
7364866a8a Merge pull request #477 from RustPython/dict7
Remove support for module get_item
2019-02-16 11:11:52 +11:00
Tom Schuster
4762d654b4 implement set.discard 2019-02-15 20:46:00 +01:00
janczer
b9daabfc94 Remove return, use function without closure 2019-02-15 20:43:20 +01:00
janczer
c1f6d16079 Change iterator to for loop 2019-02-15 20:33:41 +01:00
silmeth
4a67bb9797 stop dividing the divisor if the remainder already disappeared 2019-02-15 20:08:28 +01:00
janczer
4726d6b8b0 Remove unwrap methods 2019-02-15 20:01:02 +01:00
silmeth
4cfd3a1cd0 get rid of unnecessary muts in objint::div_ints 2019-02-15 19:50:25 +01:00
janczer
1e92bb892e Fix fmt in set.copy 2019-02-15 19:48:48 +01:00
janczer
f45f307a55 Add copy method to list object 2019-02-15 19:48:48 +01:00
silmeth
8ed82a089f make big ints dividable if the result fits in a float 2019-02-15 19:43:00 +01:00
silmeth
0c626dd595 rename objstr::get_value_as_ref to objstr::borrow_value 2019-02-15 19:29:58 +01:00
Windel Bouwman
0c351ea76d Remove support for module get_item 2019-02-15 17:30:28 +01:00
Windel Bouwman
2d22a882ae Merge pull request #475 from palaviv/Add-set-funcs3
Add set.{union,intersection,difference,symmetric_difference}
2019-02-15 17:08:10 +01:00
Windel Bouwman
b785960a25 Merge pull request #461 from adrian17/arg_check_refactor
Refactor arg_check macro
2019-02-15 16:59:09 +01:00
janczer
9e719b6cb8 Move test to list.py 2019-02-15 16:53:36 +01:00
Windel Bouwman
a541b509a9 Merge branch 'master' into Add-set-funcs3 2019-02-15 16:53:10 +01:00
Windel Bouwman
1611aa42c1 Merge pull request #476 from palaviv/set-unhashable
set raises TypeError when unhashable element is passed in creation
2019-02-15 16:50:05 +01:00
Aviv Palivoda
412df7472f set raises TypeError when unhashable element is passed in creation 2019-02-15 15:34:55 +02:00
Aviv Palivoda
49e10ed497 Add set.symmetric_difference 2019-02-15 15:13:05 +02:00
Aviv Palivoda
938688cb69 Add set.difference 2019-02-15 15:13:05 +02:00
Aviv Palivoda
23ef487927 Add set.intersection 2019-02-15 15:13:05 +02:00
Aviv Palivoda
83c4eda62c Add set.union 2019-02-15 15:13:05 +02:00
janczer
2ac195e539 List remove, handle non exist element. Add new test 2019-02-15 08:49:58 +01:00
Windel Bouwman
48032a5110 Merge pull request #472 from OddCoincidence/int-float-rarithmetic
Add {int,float}.{__radd__,__rsub__,__rmul__,__rtruediv__}
2019-02-15 07:14:01 +01:00
Windel Bouwman
a2d4924909 Merge pull request #469 from janczer/fix_typos
Fix typos
2019-02-15 07:03:04 +01:00
Windel Bouwman
ddbd7d759f Merge pull request #471 from OddCoincidence/fstring-fixes-and-tests
Fix f-string edge case and add more tests
2019-02-15 07:02:27 +01:00
Joey Hain
c6ac393f84 Add {int,float}.{__radd__,__rsub__,__rmul__,__rtruediv__} 2019-02-14 21:21:30 -08:00
Joey Hain
fb4d55bd8f Fix f-string edge case and add more tests 2019-02-14 18:46:23 -08:00
janczer
358f9f764b Add remvoe to list object 2019-02-14 21:18:38 +01:00
janczer
89e947a04f Fix typos 2019-02-14 20:38:18 +01:00
Windel Bouwman
d76c86ed16 Merge pull request #468 from janczer/add_complex_real_imag
Add complex methods real and imag
2019-02-14 17:59:40 +01:00
janczer
2a2ddff14e Add complex methods real and imag 2019-02-14 16:56:32 +01:00
Windel Bouwman
518b37185e Merge pull request #466 from OddCoincidence/fstrings
Initial support for f-strings (i.e. strings with interpolated expressions)
2019-02-14 12:22:27 +01:00
ZapAnton
f1654cb890 Migrated the project to the Rust 2018 edition 2019-02-14 12:02:32 +03:00
Joey Hain
bc4e48ae61 Fix tests 2019-02-13 23:32:55 -08:00
Joey Hain
4ca3d3b507 Merge remote-tracking branch 'upstream/master' into fstrings 2019-02-13 23:16:40 -08:00
Joey Hain
a97e05a164 Add missing semicolon to Bytes rule 2019-02-13 23:11:54 -08:00
Joey Hain
7d743de43f fix another edge case 2019-02-13 22:28:16 -08:00
Windel Bouwman
33d272f795 Merge pull request #464 from holygits/internal-error-types
Introduce Parser and Compiler Errors
2019-02-14 07:07:21 +01:00
Joey Hain
400ad80b64 fstrings 2019-02-13 21:59:21 -08:00
holygits
570b28439a Fix tests 2019-02-14 12:31:20 +13:00
Nick Hynes
ae8dc46947 Allow compiling VM for wasm32-unknown-unknown 2019-02-13 23:22:03 +00:00
holygits
995fac12fd Remove stray file 2019-02-14 11:10:27 +13:00
Windel Bouwman
d048d0a0da Merge pull request #445 from RustPython/co_consts
Co consts
2019-02-13 22:59:53 +01:00
Windel Bouwman
116f5daae4 Merge pull request #450 from silmeth/microopt-print
Fix crashes on wrong kwargs types to print + microoptimize it
2019-02-13 22:59:07 +01:00
Windel Bouwman
a8873dbaff Merge pull request #460 from janczer/add_clear_method_set
Add clear method to set
2019-02-13 22:51:18 +01:00
holygits
f0d7c2bea9 Fix test 2019-02-14 10:46:48 +13:00
holygits
4453c3e561 Create error types for parser and compiler
Pass through locations and tokens in ParseError
2019-02-14 10:21:21 +13:00
Adam
b88b87f210 Merge pull request #462 from adrian17/lambda_parsing
Change lambda parsing to be closer to Python official grammar. Fixes #427
2019-02-13 20:44:55 +00:00
Adam
233242c3ad Merge pull request #429 from adrian17/master
Fix callable(), add tests.
2019-02-13 20:38:27 +00:00
Adrian Wielgosik
21299ecf3d Refactor arg_check macro 2019-02-13 21:05:23 +01:00
Adrian Wielgosik
7dfb0728fd Change lambda parsing to be closer to Python grammar. Fixes #427 2019-02-13 21:01:13 +01:00
janczer
b77165c5ad Fix fmt set.clear 2019-02-13 14:44:50 +01:00
janczer
d07b3dff98 Add clear method to set 2019-02-13 14:37:05 +01:00
Ryan Liddle
3d4fd5fc86 Merge pull request #456 from yuvipanda/os-name
Implement os.name
2019-02-13 19:35:32 +11:00
Ryan Liddle
c6c1e7f60e Merge pull request #453 from OddCoincidence/int-float-comparison
Fix int to float comparison
2019-02-13 19:31:00 +11:00
yuvipanda
252c3be5f8 Add newline to os_info test file 2019-02-13 00:01:06 -08:00
yuvipanda
9dc45fd728 Implement os.name 2019-02-12 23:51:36 -08:00
Windel Bouwman
392262d3f4 Merge pull request #454 from janczer/call_wrap_functions
Call wrap functions insted of magic
2019-02-13 07:05:26 +01:00
Windel Bouwman
db7a64fe5a Merge pull request #451 from adrian17/list_copy
Add list.copy()
2019-02-13 07:04:24 +01:00
Windel Bouwman
74c5d4dae1 Merge pull request #452 from matrizx/master
Replaced cluttered match statements with if let
2019-02-13 07:02:48 +01:00
Joey Hain
5fd912b13a Remove float comparisons from int.__eq__, add int.__ne__ 2019-02-12 21:56:25 -08:00
janczer
4959defff8 Call wrap functions insted of magic 2019-02-13 06:34:44 +01:00
Joey Hain
2041b7cef6 Fix int to float comparison 2019-02-12 18:44:03 -08:00
matrizx
c041c8cbc5 Replaced cluttered match statements with if let 2019-02-12 16:55:12 -08:00
Adrian Wielgosik
ecfc70ef99 Add list.copy() 2019-02-13 00:21:42 +01:00
silmeth
bd64869686 fix None kwargs to print in vm and in wasm_builtins 2019-02-12 23:17:17 +01:00
silmeth
a2ab4473a3 add tests of error handling for wrong types of print() kwargs 2019-02-12 22:33:54 +01:00
silmeth
3d17cc0aa1 copy print() kwargs handling over to wasm_builtins 2019-02-12 22:27:04 +01:00
silmeth
7b7aa13295 microoptimize print (lock stdout, borrow strings) 2019-02-12 22:25:46 +01:00
Adrian Wielgosik
a8f650b709 Fix callable(), add tests. 2019-02-12 19:26:10 +01:00
Windel Bouwman
e5af4caecf Merge pull request #424 from janczer/add_object_lt_le_gt_ge
Add object.{__lt__, __le__, __gt__, __gt__}
2019-02-12 19:21:07 +01:00
Windel Bouwman
de98ac696b Merge pull request #442 from OddCoincidence/float-parsing
Support float(<str>) and float(<bytes>)
2019-02-12 18:45:50 +01:00
janczer
9277e67b15 Add not_implemented to float.{__le__, __gt__, __ge__} 2019-02-12 18:32:26 +01:00
janczer
9601673044 Fix the reflections of methods lt, le, gt, ge 2019-02-12 18:20:04 +01:00
janczer
1ff1bcda6b Fix the call __gt__ 2019-02-12 17:56:11 +01:00
Windel Bouwman
17bde53ca3 Add end kwarg to print function. 2019-02-12 17:23:33 +01:00
Windel Bouwman
2645bfd47a Merge pull request #448 from ZapAnton/fix_clippy_warnings
Fixed several clippy warnings
2019-02-12 17:05:53 +01:00
Windel Bouwman
a75eea56ab Merge pull request #446 from RustPython/none_str
Add __repr__ and __new__ to NoneType.
2019-02-12 17:00:46 +01:00
janczer
0887b55da8 Add object.{__lt__, __le__, __gt__, __gt__} 2019-02-12 15:32:07 +01:00
ZapAnton
604883dc86 Fixed the len_zero clippy warning 2019-02-12 17:13:09 +03:00
ZapAnton
08d767b010 Fixed the unnecessary_mut_passed clippy warning 2019-02-12 17:12:11 +03:00
ZapAnton
e8467c3bfe Fixed the redundant_closure clippy warning 2019-02-12 17:10:53 +03:00
ZapAnton
a0f1f51863 Fixed the useless_asref clippy warnings 2019-02-12 17:09:52 +03:00
ZapAnton
ef65612008 Fixed the clone_double_ref clippy warning 2019-02-12 16:59:15 +03:00
ZapAnton
206ccc55fb Fixed the len_without_is_empty clippy warning 2019-02-12 16:49:34 +03:00
ZapAnton
38930984ec Fixed the redundant_pattern_matching clippy warning 2019-02-12 16:45:44 +03:00
ZapAnton
291dba6bb6 Fixed the toplevel_ref_arg clippy warning 2019-02-12 16:44:47 +03:00
ZapAnton
5fe373555f Fixed the match_bool clippy warning 2019-02-12 16:43:59 +03:00
ZapAnton
45b9ef9719 Fixed the op_ref clippy warnings 2019-02-12 16:42:53 +03:00
ZapAnton
050bf459b0 Fixed the into_iter_on_ref clippy warning 2019-02-12 16:40:08 +03:00
ZapAnton
9144109f7d Fixed the useless_vec clippy warning 2019-02-12 16:39:38 +03:00
ZapAnton
66569160fc Fixed the redundant_closure clippy warning 2019-02-12 16:38:15 +03:00
ZapAnton
8b6d0b3721 Fixed the op_ref clippy warning 2019-02-12 16:37:02 +03:00
ZapAnton
00cfa47f64 Fixed the should_implement_trait clippy warning 2019-02-12 16:35:28 +03:00
ZapAnton
606ddd2216 Fixed the needless_return clippy warnings 2019-02-12 16:30:03 +03:00
ZapAnton
0d1b85a8da Fixed the collapsible_if clippy warning 2019-02-12 16:28:49 +03:00
ZapAnton
d86ffc40f6 Fixed the redundant_field_names clippy warnings 2019-02-12 16:07:24 +03:00
Adam Kelly
a735bb3dfc Add __repr__ and __new__ to NoneType. 2019-02-12 10:09:13 +00:00
Adam Kelly
8a89e13a7e Add .co_consts to code class. 2019-02-12 09:47:02 +00:00
Adam Kelly
8cc2d5f091 Move implementation of CodeObject after Instructions. 2019-02-12 09:40:55 +00:00
Adam
8835b47d1f Merge pull request #444 from skinny121/object_format
Add object.__format__
2019-02-12 08:52:20 +00:00
ben
d14aeef2e5 Handle passing no format_spec into format() 2019-02-12 20:24:57 +13:00
ben
5c12367f59 Merge branch 'master' into object_format 2019-02-12 20:09:27 +13:00
ben
93e5634d39 Fixes #328, add object.__format__ 2019-02-12 20:06:50 +13:00
Windel Bouwman
9177252cf9 Merge pull request #259 from RustPython/list_insert
Implemented list.insert()
2019-02-12 06:10:20 +01:00
Windel Bouwman
d0d27babba Merge pull request #443 from OddCoincidence/fix-typo
Fix typo in VirtualMachine::_and
2019-02-12 06:06:31 +01:00
Joey Hain
beb75a4dd0 Fix typo in VirtualMachine::_and 2019-02-11 19:51:17 -08:00
Joey Hain
38c0ea06e5 Support float(<str>) and float(<bytes>) 2019-02-11 19:40:55 -08:00
Windel Bouwman
6f0ac744f2 Merge pull request #441 from RustPython/dont_call__eq__
Dont call  eq
2019-02-11 23:17:29 +01:00
Shing Lyu
d188f05ffc Fix errors introduced during rebasing 2019-02-11 22:59:08 +01:00
Shing Lyu
b265601c58 Use isize in list.insert instead of i64 2019-02-11 22:52:55 +01:00
Shing Lyu
3467db51d0 Simplify the number logic for list.insert() 2019-02-11 22:52:55 +01:00
Shing Lyu
c99cb0c366 Rustfmt fixes 2019-02-11 22:52:55 +01:00
Shing Lyu
8ded37d566 Raise OverflowError is the index for list.index() overflows 2019-02-11 22:52:27 +01:00
Shing Lyu
b101a52dd0 Added list.insert() 2019-02-11 22:50:10 +01:00
Shing Lyu
cc407ed90a Merge pull request #412 from veera83372/travis-clippy
added cargo clippy to travis
2019-02-11 22:44:58 +01:00
Windel Bouwman
cb59d76900 Merge pull request #439 from RustPython/move_unwrap_constant
Move unwrap_constant from Frame to PyContext.
2019-02-11 22:11:47 +01:00
Adam Kelly
67710d6e28 Don't call __eq__ directly.
Doing so creates a very confusing error when NotImplemented in returned.
2019-02-11 21:11:33 +00:00
Adam Kelly
50be99a0a1 Failing test case for in and index where types don't match. 2019-02-11 21:11:33 +00:00
Adam
23aa4a71ea Merge pull request #436 from Tom1380/master
Fix #390.
2019-02-11 21:09:32 +00:00
Adam Kelly
860edc6dfe Move unwrap_constant from Frame to PyContext. 2019-02-11 15:52:19 +00:00
Adam
89495e102a Merge pull request #418 from veera83372/format-exception
Fixing assert second argument formatting
2019-02-11 13:06:07 +00:00
Adam
1033f20e36 Merge pull request #430 from RustPython/dict5
Change to more usage of VirtualMachine in anticipation of proper dicts
2019-02-11 13:04:28 +00:00
Adam
ca51f2d10e Merge pull request #438 from ZapAnton/fix_clippy
Fixed several small clippy warnings
2019-02-11 13:03:07 +00:00
Tommaso Thea Cioni
7e1589d811 Minor fix. 2019-02-11 13:38:53 +01:00
Adam
45f45bf43a Merge pull request #433 from OddCoincidence/not-implemented
Use NotImplemented in binary operations
2019-02-11 12:37:22 +00:00
Tommaso Thea Cioni
c04f4219eb Removed the __code__ attribute from the builtin_function_or_method type. 2019-02-11 13:35:59 +01:00
ZapAnton
e51c75e1df Fixed or_fun_call clippy warnings 2019-02-11 15:29:19 +03:00
ZapAnton
56e2d4c495 Fixed into_iter_on_ref clippy warning 2019-02-11 15:24:51 +03:00
ZapAnton
c8d619c123 Fixed useless_let_if_seq clippy warnings 2019-02-11 15:24:13 +03:00
Tommaso Thea Cioni
cc56f318cb Merge branch 'master' of https://github.com/RustPython/RustPython 2019-02-11 13:21:41 +01:00
Adam
5c378d3bc5 Merge pull request #437 from rmliddle/develop
OS Tidy and Name fix
2019-02-11 12:17:40 +00:00
ZapAnton
d5b87558a2 Fixed map_clone clippy warnings 2019-02-11 15:09:53 +03:00
ZapAnton
1043543f16 Fixed cast_lossless clippy warnings 2019-02-11 15:02:00 +03:00
ZapAnton
b1a4aea9f3 Fixed explicit_counter_loop clippy warning 2019-02-11 14:59:22 +03:00
rmliddle
dd7437242c os rename 2019-02-11 21:41:47 +11:00
rmliddle
55a22c5a71 Fix module name in os 2019-02-11 21:40:00 +11:00
Tommaso Thea Cioni
8ac3c46de1 Fix RustPython#390. Now Rust functions have a builtin_function_or_method type, Python functions retain the function type. 2019-02-11 02:50:51 +01:00
Joey Hain
057a22529e Move delegation of __ne__ to __eq__ out of objobject 2019-02-10 15:46:12 -08:00
Joey Hain
a510aed86a Tests and fix objobject ne impl 2019-02-10 10:13:30 -08:00
Windel Bouwman
7102128654 Merge pull request #432 from HomerMcMillan/range-properties
Range properties
2019-02-10 18:21:44 +01:00
Joey Hain
dab4f7385f Use NotImplemented in binary operations 2019-02-10 09:19:06 -08:00
Homer McMillan
389fc3acd9 cargo fmt 2019-02-10 12:04:42 -05:00
Homer McMillan
9de733be19 Add range start/stop/step 2019-02-10 12:03:22 -05:00
Homer McMillan
10c2099374 Merge remote-tracking branch 'upstream/master' 2019-02-10 11:27:19 -05:00
Windel Bouwman
accfac8c41 Merge pull request #431 from janczer/add_str_le_ge
Fix the str.{__lt__, __gt__} and add the methods str.{__le__, __ge__}
2019-02-10 17:15:05 +01:00
janczer
aac1ce4e07 Fix the str.{__lt__, __gt__} and add the methods str.{__le__, __ge__} 2019-02-10 16:40:09 +01:00
Windel Bouwman
b1e07f64be Change to more usage of VirtualMachine in anticipation of proper dictionaries. 2019-02-10 15:39:33 +01:00
Windel Bouwman
05cd60bebc Merge pull request #415 from silmeth/fix-int-eq-float
fix int – float equality for big ints, inf and nan
2019-02-10 13:55:50 +01:00
silmeth
2182fa1bf5 rename old math tests (conflicting with math library imports) 2019-02-10 13:33:45 +01:00
Windel Bouwman
cf31805c2c Fix set test by add __hash__ method. 2019-02-10 13:30:22 +01:00
Windel Bouwman
68002f1a9e Fix build error of removed str method. 2019-02-10 13:00:54 +01:00
Windel Bouwman
9497ee89e8 Merge pull request #292 from mcon/sets-using-hashes
Items are now added to sets using proper __hash__ function calls.
2019-02-10 12:57:46 +01:00
Windel Bouwman
1cb59c5731 Merge pull request #394 from ZapAnton/iter_doc
iter type: Added __doc__
2019-02-10 12:28:09 +01:00
Windel Bouwman
2bab31b8e7 Merge pull request #387 from janczer/add_bytes_ge_gt_le_lt
Add bytes.{__ge__, __gt__, __le__, __lt__}
2019-02-10 12:27:01 +01:00
Windel Bouwman
03a2aad82d Merge pull request #410 from OddCoincidence/complex
Add complex.{__abs__, __eq__, __neg__}
2019-02-10 12:23:24 +01:00
veera venky
9bc9befee6 Added exception string when msg can't be converted to string 2019-02-10 16:43:21 +05:30
Windel Bouwman
c2db23db2b Merge pull request #417 from janczer/fix_lt_le_ge_gt_float
float.{__lt__, __le__, __ge__, __gt__} fix comparing with non float type
2019-02-10 12:10:58 +01:00
Windel Bouwman
fc38d55b59 Merge pull request #381 from nficca/implement-range-count
Implement range.count
2019-02-10 11:46:10 +01:00
Windel Bouwman
94db145ae8 Merge branch 'master' into complex 2019-02-10 11:41:39 +01:00
Windel Bouwman
e69605328b Merge pull request #426 from skinny121/recursive_repr
Fixed #191, fixes recursive repr() for the standard collections
2019-02-10 08:35:02 +01:00
Windel Bouwman
e98d5f11cc Merge pull request #393 from ZapAnton/filter_doc
filter type: Added __doc__
2019-02-10 08:24:50 +01:00
Ryan Liddle
7422d27201 Merge pull request #422 from HomerMcMillan/range-reversed
Fix range reversed #421
2019-02-10 15:08:34 +11:00
ben
5b637385ea Fixed #191, fixes recursive repr() for the standard collections 2019-02-10 13:22:03 +13:00
Homer McMillan
0611e765e2 Add extra test to builtin_range.py 2019-02-09 18:40:46 -05:00
Homer McMillan
58e05d28f6 Merge remote-tracking branch 'upstream/master' 2019-02-09 18:15:45 -05:00
Adam
d8afc6a722 Merge pull request #420 from Tom1380/master
Uncommented a line of code like a TODO said.
2019-02-09 22:36:50 +00:00
Matthew Constable
0322b937f3 Updated formatting 2019-02-09 21:58:01 +00:00
Matthew Constable
9271bfcb84 Moved from using BigInt in set hash to u64, which is guaranteed to be of constant size - u64 seems easier than usize as it's the same size across all platforms. 2019-02-09 21:57:26 +00:00
Nic Ficca
0cb661f3a2 Dry up objrange
- Use get_value in all appropriate spots
2019-02-09 16:54:14 -05:00
Nic Ficca
2e9892029a Add objrange::get_value
- Refactor range_count to use get_value and isinstance for pulling out the range and argument respectively
2019-02-09 16:49:44 -05:00
Matthew Constable
cca16ff597 Simplify calling __hash__ method 2019-02-09 21:38:11 +00:00
Nic Ficca
316e94bd42 Add tests 2019-02-09 16:28:04 -05:00
Nic Ficca
b7a4248837 Add range.count 2019-02-09 16:27:12 -05:00
Matthew Constable
9f3cc35e9c Allow sets to be initialized from literals. 2019-02-09 21:24:16 +00:00
Matthew Constable
c673384cc4 Merge branch 'master' into sets-using-hashes 2019-02-09 21:04:33 +00:00
Homer McMillan
ba9226219b cargo fmt 2019-02-09 15:54:17 -05:00
Homer McMillan
a4d13f9f50 Fix typo 2019-02-09 15:53:13 -05:00
Homer McMillan
4e02962289 Fix range reversed #421 2019-02-09 15:49:51 -05:00
ZapAnton
216e690ee0 filter type: Added __doc__ 2019-02-09 23:00:43 +03:00
Tommaso Thea Cioni
b9d773824c Uncommented a line of code like a TODO said. 2019-02-09 20:24:24 +01:00
Windel Bouwman
ecea7035b0 Merge branch 'master' into iter_doc 2019-02-09 19:37:17 +01:00
Windel Bouwman
ac37026010 Merge pull request #385 from OddCoincidence/reversed
Add reversed builtin and range.__reversed__
2019-02-09 19:32:44 +01:00
Windel Bouwman
56a36b7959 Merge pull request #395 from ZapAnton/map_doc
map type: Added __doc__
2019-02-09 19:31:32 +01:00
Joey Hain
d3d73bdc22 Disable broken test for now 2019-02-09 10:24:17 -08:00
janczer
454837f64b Fix fmt in objfloat 2019-02-09 19:16:04 +01:00
Tommaso Thea Cioni
8ffd4c5e56 Fixed #402. (#414)
Raise syntax error rather than panicking on expected closing bracket. 

* Fixed #402.
2019-02-09 18:10:40 +00:00
Windel Bouwman
7807dc3d2c Merge pull request #388 from veera83372/sys-doc
Added __doc__ for sys module
2019-02-09 18:59:45 +01:00
Windel Bouwman
b14dc20adc Merge branch 'master' into map_doc 2019-02-09 18:58:37 +01:00
veera venky
b5911ed796 Fixing assert second argument formatting 2019-02-09 22:17:01 +05:30
Joey Hain
22a430cdc5 Don't use magic methods directly 2019-02-09 08:20:04 -08:00
Joey Hain
969ddf2ea0 Merge remote-tracking branch 'upstream/master' into reversed 2019-02-09 08:13:03 -08:00
Joey Hain
09dc751869 Avoid using magic methods in tests where possible 2019-02-09 08:09:48 -08:00
janczer
8d1d6ce1ee float.{__lt__, __le__, __ge__, __gt__} fix comparing with non float type 2019-02-09 17:05:32 +01:00
janczer
607e1262d4 Fix the typo 2019-02-09 16:42:32 +01:00
Windel Bouwman
3c25c14311 Merge pull request #400 from palaviv/Add-set-funcs
Add set.{__eq__,__gt__,__ge__,__le__,__lt__,issubset,issuperset}
2019-02-09 16:31:05 +01:00
Windel Bouwman
601e4c9dc9 Merge pull request #416 from silmeth/zero-division
fix floordiv and divmod by zero for ints and floats
2019-02-09 16:29:52 +01:00
Windel Bouwman
95cb0178cd Merge pull request #405 from RustPython/code_object
Code object
2019-02-09 16:20:07 +01:00
silmeth
6c56c22f0f fix floordiv and divmod by zero for ints and floats 2019-02-09 15:15:54 +01:00
silmeth
d960ca3d5b fix int – float equality for big ints, inf and nan 2019-02-09 14:02:43 +01:00
Adam Kelly
5c5d27203a Support for all co_* that can implemented currently. 2019-02-09 12:22:51 +00:00
Adam Kelly
6539f07818 @generated comment added to Cargo.lock 2019-02-09 12:22:51 +00:00
Adam Kelly
769b889097 Source path should always be set, make it non-optional for code object. 2019-02-09 12:22:51 +00:00
Adam
a6d6f0fcaa Merge pull request #413 from ka7/spelling
Spelling fixes
2019-02-09 12:18:09 +00:00
Adam Kelly
1869a9f1ed Passing version of code.py tests. 2019-02-09 12:15:16 +00:00
Adam Kelly
8116dae65f Add some co_* methods to code objects. 2019-02-09 12:15:16 +00:00
Adam Kelly
7d08867419 Record first line number in code object. 2019-02-09 12:15:16 +00:00
Adam Kelly
7b2508a730 Start adding methods to code object. 2019-02-09 12:15:16 +00:00
Adam
8ad95c4a57 Merge pull request #326 from lausek/master
int type: rounding, index, trunc, int (#304)
2019-02-09 11:23:14 +00:00
Adam
b87fcdce34 Merge pull request #285 from orf/handle-missing-file
Improve test coverage of os.open/open
2019-02-09 11:20:11 +00:00
Adam
2ae9d88de4 Merge pull request #398 from ZapAnton/range_doc
range type: Added __doc__
2019-02-09 11:11:13 +00:00
klemens
b109ea954a Merge branch 'master' into spelling 2019-02-09 12:03:08 +01:00
Adam
c5b94a4d82 Merge pull request #408 from janczer/add_floats_div_mul
Add floats.{__truediv__, __mul__}
2019-02-09 11:03:01 +00:00
klemens
79a7e5e42b spelling fixes 2019-02-09 12:00:46 +01:00
veera venky
fa927c5028 added cargo clippy 2019-02-09 16:25:29 +05:30
Aviv Palivoda
2df9d799f5 Fix formatting errors 2019-02-09 10:18:05 +02:00
Windel Bouwman
3376808428 Merge pull request #409 from skinny121/slice
Add slice type
2019-02-09 08:31:55 +01:00
Windel Bouwman
587617d5e3 Add dict data type. (#380)
* Add dict data type.

* Fix formatting.

* Implement review comments.
2019-02-09 08:14:37 +01:00
Joey Hain
520f71f354 Add NotImplemented built-in constant 2019-02-08 19:24:08 -08:00
ben
7abf02180a implement slice negative step handling 2019-02-09 15:48:07 +13:00
Joey Hain
d66ca54a2d Add complex.{__eq__, __neg__} 2019-02-08 18:20:58 -08:00
Joey Hain
fc863aaba5 Add complex.__abs__ 2019-02-08 18:20:55 -08:00
ben
907dfb6770 Add slice type and use BigInts in slice payload. 2019-02-09 12:07:04 +13:00
janczer
ba19732fbb Fix the fmt error 2019-02-08 22:09:42 +01:00
janczer
47fc303e55 Rasi error when try compare bytes with another types 2019-02-08 22:06:57 +01:00
janczer
59706538f4 Fix typo and fix fmt errors 2019-02-08 21:56:07 +01:00
Windel Bouwman
f454bf36d1 Merge pull request #396 from ZapAnton/property_doc
property type: Added __doc__
2019-02-08 21:16:17 +01:00
Windel Bouwman
85475e4e30 Merge pull request #347 from silmeth/master
Fix Range’s len() + division and mod by 0
2019-02-08 21:04:31 +01:00
janczer
d4b82007df Add floats.{__truediv__, __mul__} 2019-02-08 20:34:33 +01:00
Windel Bouwman
869b91a27d Merge pull request #399 from ZapAnton/super_doc
super type: Added __doc__
2019-02-08 20:08:22 +01:00
Windel Bouwman
32bfcf36fd Merge pull request #384 from skinny121/iter_lazy_2
Add enumerate and zip types
2019-02-08 20:05:20 +01:00
Adam
c55593406c Merge pull request #392 from ZapAnton/complex_doc
complex type: Added __doc__
2019-02-08 18:31:26 +00:00
Adam
f5792f84d6 Merge pull request #391 from ZapAnton/byteaaray_doc
bytearray type: Added __doc__
2019-02-08 18:31:03 +00:00
Adam
9245a62296 Merge pull request #401 from ZapAnton/type_doc
type type: Added __doc__
2019-02-08 18:30:17 +00:00
Adam
891b79bbb6 Merge pull request #403 from ZapAnton/remove_doc_tests
tests: Removed tests for the __doc__
2019-02-08 18:29:29 +00:00
Adam
bf294a82e8 Merge pull request #404 from ZapAnton/fix_if_same_then_else
Fix the 'if_same_then_else' clippy warnings
2019-02-08 18:29:02 +00:00
Benedykt Jaworski
b9245309d5 Merge branch 'master' into master 2019-02-08 18:45:00 +01:00
ZapAnton
0e6fca0106 Fix the 'if_same_then_else' clippy warnings
Relevant clippy warning: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
2019-02-08 20:04:30 +03:00
veera venky
cf2d07502b Removed strict testing for __doc__ string 2019-02-08 22:26:28 +05:30
ZapAnton
da68dfef78 tests: Removed tests for the __doc__ 2019-02-08 19:41:47 +03:00
ZapAnton
ae88389e10 type type: Added __doc__ 2019-02-08 19:36:10 +03:00
Aviv Palivoda
9ec2eef579 Add set.{issubset,issuperset} 2019-02-08 18:33:04 +02:00
ZapAnton
2b0f87b69f super type: Added __doc__ 2019-02-08 19:28:39 +03:00
Aviv Palivoda
2bc946b748 Add set.__lt__ 2019-02-08 18:27:37 +02:00
Aviv Palivoda
adee66168b Add set.__le__ 2019-02-08 18:25:33 +02:00
ZapAnton
a6d6f7721b range type: Added __doc__ 2019-02-08 19:17:08 +03:00
ZapAnton
a6beeac383 property type: Added __doc__ 2019-02-08 19:09:38 +03:00
Aviv Palivoda
1ee583ef61 Use set_compare_inner 2019-02-08 18:06:22 +02:00
ZapAnton
c05f7dc83a map type: Added __doc__ 2019-02-08 19:01:18 +03:00
ZapAnton
e6d638d43f iter type: Added __doc__ 2019-02-08 18:56:34 +03:00
Aviv Palivoda
358aa6b2c0 Add set.__gt__ 2019-02-08 17:50:36 +02:00
ZapAnton
031f062e72 complex type: Added __doc__ 2019-02-08 18:47:23 +03:00
ZapAnton
a180a4b6cb bytearray type: Added __doc__ 2019-02-08 18:43:27 +03:00
veera venky
61cbb49647 Added __doc__ for sys module 2019-02-08 21:08:30 +05:30
Aviv Palivoda
0c737ae8d2 Add set.__eq__ 2019-02-08 17:31:45 +02:00
Aviv Palivoda
6274c3fe8b Add set.__ge__ 2019-02-08 17:18:14 +02:00
Windel Bouwman
07fd61f55f Change instance and class to simplified dict type. (#379)
* Change instance and class to simplified dict type.

* Fix formatting.
2019-02-08 14:18:14 +00:00
janczer
83202d639f Add bytes.{__ge__, __gt__, __le__, __lt__} 2019-02-08 15:02:50 +01:00
Joey Hain
1ebacafb00 Add reversed builtin and range.__reversed__ 2019-02-08 00:19:14 -08:00
ben
e1284e34b0 Made filter_new private 2019-02-08 21:05:04 +13:00
ben
5896f049ef Add enumerate and zip types and made them lazy. 2019-02-08 20:57:16 +13:00
Windel Bouwman
a4b99253c9 Merge pull request #382 from OddCoincidence/range-bool-contains
Add range.{__bool__, __contains__}
2019-02-08 08:05:40 +01:00
Joey Hain
54bcb08518 Add range.{__bool__, __contains__}
- Also fix range.index for negative steps
2019-02-07 20:31:32 -08:00
Windel Bouwman
3dc2ab979d Merge pull request #378 from veera83372/tuple-methods
Added __doc__ atrribute for tuple
2019-02-07 21:09:18 +01:00
Windel Bouwman
385fb03d7a Merge pull request #327 from ZapAnton/float_doc
Float type: Added __doc__
2019-02-07 21:08:42 +01:00
veera venky
b85cf91a23 Added __doc__ atrribute for tuple 2019-02-07 23:47:47 +05:30
Windel Bouwman
3d2d04596c Merge pull request #343 from ZapAnton/fix_various_clippy
Fixed various small clippy warnings
2019-02-07 17:35:29 +01:00
Windel Bouwman
4e584efa57 Merge pull request #374 from ZapAnton/set_doc
(frozen)set type: Added __doc__
2019-02-07 17:29:07 +01:00
Windel Bouwman
c24a88c5ad Merge pull request #369 from ZapAnton/bytes_doc
bytes type: Added __doc__
2019-02-07 17:28:25 +01:00
Benedykt Jaworski
f823eb9403 Merge branch 'master' into master 2019-02-07 17:20:54 +01:00
Tom Forbes
6c18126382 Improve test coverage of os.open 2019-02-07 07:30:53 -07:00
Ryan Liddle
4d02a1e037 Merge pull request #376 from veera83372/tuple-index
Added index to tuple
2019-02-07 21:49:26 +11:00
veera venky
1479d6bc77 Added index to tuple 2019-02-07 14:56:14 +05:30
Windel Bouwman
d3158f3db5 Merge pull request #372 from RustPython/eliminate_repeated_to_bigint
Eliminate repeated to bigint
2019-02-07 06:22:58 +01:00
ZapAnton
694cbda03d (frozen)set type: Added __doc__ 2019-02-07 00:57:29 +03:00
Windel Bouwman
8f2c959143 Merge pull request #368 from ZapAnton/list_doc
list type: Added __doc__
2019-02-06 20:44:39 +01:00
Adam Kelly
df89c439d9 Fix accidentally broken test. 2019-02-06 17:55:01 +00:00
lausek
02d99758fe round() for int 2019-02-06 18:38:37 +01:00
Adam Kelly
fd344ec1e0 Remove unnecessary to_bigint().unwrap() everywhere. 2019-02-06 17:38:01 +00:00
Adam Kelly
aca0238379 Allow new_int to take anything with ToBigInt. 2019-02-06 17:36:22 +00:00
Adam Kelly
a83fd7c1af Add __code__ to functions. 2019-02-06 16:01:07 +00:00
Windel Bouwman
eb0da4f61c Merge pull request #366 from rmliddle/develop
Fixes build on Windows
2019-02-06 14:15:30 +01:00
ZapAnton
ca63f899d6 list type: Added __doc__ 2019-02-06 15:18:45 +03:00
ZapAnton
1992e02b76 bytes type: Added __doc__ 2019-02-06 15:16:41 +03:00
ZapAnton
2d7164df92 float type: Added __doc__ 2019-02-06 14:44:30 +03:00
rmliddle
f89dc0061b included all not unix in static pathbuf 2019-02-06 22:37:35 +11:00
rmliddle
51d5f9d3a4 changed String to PathBuf 2019-02-06 21:46:50 +11:00
ZapAnton
3464828499 Fixed various small clippy warnings 2019-02-06 13:24:24 +03:00
Windel Bouwman
03fb016415 Merge pull request #333 from ZapAnton/fix_useless_format
Fixed the 'useless_format' clippy warning
2019-02-06 11:16:21 +01:00
rmliddle
401f477fc8 Format main.rs 2019-02-06 21:01:55 +11:00
Ryan Liddle
9e53091c0f Merge branch 'implement-io' of https://github.com/rmliddle/RustPython into implement-io 2019-02-06 21:00:37 +11:00
Ryan Liddle
2f0647e847 factored out xdg to cfg functions to allow windows builds to succeed 2019-02-06 20:59:54 +11:00
Windel Bouwman
c21772c969 Merge pull request #365 from ZapAnton/int_rxor
int type: Added __rxor__
2019-02-06 10:55:55 +01:00
Windel Bouwman
62cad730d3 Merge pull request #364 from HomerMcMillan/string_is_methods
Fix string is* methods
2019-02-06 10:55:06 +01:00
Windel Bouwman
baa59ec2fc Merge branch 'master' into fix_useless_format 2019-02-06 10:50:07 +01:00
Windel Bouwman
2c693d9a2e Merge pull request #336 from ZapAnton/fix_redundant_field_names
Fixed the 'redundant_field_names' clippy warnings
2019-02-06 10:48:45 +01:00
Benedykt Jaworski
ff244df3eb Merge branch 'master' into master 2019-02-06 10:24:59 +01:00
silmeth
af0fdcb9e3 fix zero-division tests 2019-02-06 10:15:44 +01:00
ZapAnton
dfd0ea23c0 int type: Added tests for the __rxor__ 2019-02-06 12:08:26 +03:00
ZapAnton
b682eb939e int type: Added __rxor__ 2019-02-06 12:04:47 +03:00
Homer McMillan
00ef668022 String is* methods return false on empty string #363 2019-02-06 03:15:03 -05:00
Homer McMillan
94dc6ece64 Fix python tests that travis didn't like 2019-02-06 02:42:44 -05:00
Windel Bouwman
040a377d06 Merge branch 'master' into fix_redundant_field_names 2019-02-06 08:14:14 +01:00
Windel Bouwman
a26279111d Merge pull request #353 from OddCoincidence/range-index
Add range.index
2019-02-06 08:00:11 +01:00
Windel Bouwman
f13cb62393 Merge pull request #357 from veera83372/object-methods
Added __doc__ atrribute for object
2019-02-06 07:53:01 +01:00
Windel Bouwman
8a53547e2b Merge pull request #355 from NLincoln/compliant-complex-repr
repr() of complex numbers is compliant with cpython
2019-02-06 07:52:31 +01:00
Windel Bouwman
819e5a01e4 Merge pull request #354 from HomerMcMillan/bytes_iter
Add bytes.__iter__
2019-02-06 07:45:10 +01:00
Windel Bouwman
0a3f15ae22 Merge pull request #348 from skinny121/iter_lazy
Made filter and map lazy
2019-02-06 07:43:07 +01:00
Homer McMillan
0085470c83 Add tests for bytearray 2019-02-06 01:26:51 -05:00
Homer McMillan
1270aee628 Add is* methods to bytearray 2019-02-06 01:22:23 -05:00
veera venky
3de17b9083 Added __doc__ atrribute for object 2019-02-06 08:35:57 +05:30
coolreader18
9b6516e175 Allow closures to be passed from Python to JS if using a WASM VM 2019-02-05 21:04:24 -06:00
Nathan
12e6de0503 repr() of complex numbers is compliant with cpython 2019-02-05 20:59:41 -06:00
Homer McMillan
35a06bc428 Add bytes.__iter__ 2019-02-05 21:44:14 -05:00
Joey Hain
49a23a8483 remove misleading contains method 2019-02-05 16:26:12 -08:00
coolreader18
a24cd8368a Merge branch 'master' into wasm-vm-class 2019-02-05 17:53:21 -06:00
ben
6d494fb9ee Merge branch 'master' into iter_lazy 2019-02-06 12:46:16 +13:00
ben
6c8ec39882 Make map and filter into proper types 2019-02-06 12:45:14 +13:00
Windel Bouwman
aaf0eab530 Merge pull request #342 from ZapAnton/fix_collapsible_if
Fixed the 'collapsible_if' clippy warnings
2019-02-05 23:34:29 +01:00
Windel Bouwman
87ceed77ad Merge pull request #287 from makarchuk/float-conversion
Float Conversion for #211
2019-02-05 23:19:20 +01:00
ben
3a81fd1ef4 style: rustfmt 2019-02-06 11:15:07 +13:00
ben
6e99ad32db Added tests for when function in filter/map raises StopIteration 2019-02-06 11:12:25 +13:00
ben
f85bc13ded Fix misunderstanding about behaviour if filter function is None 2019-02-06 11:12:25 +13:00
ben
91fcd7782e Make map lazy and accept multiple iterables 2019-02-06 11:12:25 +13:00
ben
8cc6821c44 Make filter lazy 2019-02-06 11:12:25 +13:00
silmeth
77ae6621e9 add tests for range length, and for division by zero 2019-02-05 22:50:52 +01:00
silmeth
8621f3ff2b fix: register arithmetic errors in builtins module 2019-02-05 22:48:33 +01:00
Windel Bouwman
69e3571d0c Merge pull request #341 from ZapAnton/toplevel_ref_arg
Fixed the 'toplevel_ref_arg' clippy warning
2019-02-05 22:42:31 +01:00
Windel Bouwman
3fb0f32a87 Merge pull request #335 from ZapAnton/fix_ptr_arg
Fixed the 'ptr_arg' clippy warnings
2019-02-05 22:36:29 +01:00
Joey Hain
b0a2f6f87d Add range.index 2019-02-05 13:34:54 -08:00
Windel Bouwman
9d5a953c8a Merge pull request #337 from ZapAnton/fix_unneeded_field_pattern
Fixed the 'unneeded_field_pattern' clippy warnings
2019-02-05 22:34:31 +01:00
Windel Bouwman
276b51c4d5 Merge pull request #338 from stratusjerry/master
Spellcheck
2019-02-05 22:32:26 +01:00
Windel Bouwman
835a55777b Merge pull request #334 from ZapAnton/fix_len_zero
Fixed the 'len_zero' clippy warnings
2019-02-05 22:31:54 +01:00
Windel Bouwman
907ce8801f Merge pull request #339 from ZapAnton/fix_needless_return
Fixed the 'needless_return' clippy warnings
2019-02-05 22:30:32 +01:00
silmeth
30c8e477e4 style: rustfmt 2019-02-05 21:54:03 +01:00
silmeth
d96e0ecf40 make division and modulo by 0 throw ZeroDivisionError 2019-02-05 21:28:48 +01:00
silmeth
0a1eb4b91b make len(range) throw OverflowError on too big ints + impl __repr__ 2019-02-05 21:27:49 +01:00
ZapAnton
fb9fa27555 Fixed the 'redundant_field_names' clippy warnings
This replaces all the occurrences of the Struct {field : field}
with the Struct {field}.

Relevant clippy warning: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names
2019-02-05 21:56:16 +03:00
Timur
74b84d4be1 Merge branch 'float-conversion' of github.com:makarchuk/RustPython into float-conversion 2019-02-05 21:56:14 +03:00
Timur
4b2787ea1d Comment out math from tests due to Travis errors 2019-02-05 21:54:13 +03:00
silmeth
b43c511542 fix range len() for negative and non-divisible steps 2019-02-05 19:49:14 +01:00
ZapAnton
b0cbb23b43 Fixed the 'collapsible_if' clippy warnings
Relevant clippy warning: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if
2019-02-05 21:49:07 +03:00
ZapAnton
0d3b218237 Fixed the 'toplevel_ref_arg' clippy warning
This replaces all the occurrences of the
'let ref var = another_var' with the
'let var = &another_var'

Relevant clippy warning: https://rust-lang.github.io/rust-clippy/master/index.html#toplevel_ref_arg
2019-02-05 21:45:56 +03:00
ZapAnton
526ed98d93 Fixed the 'needless_return' clippy warnings
This replaces all the occurrences of the 'return var;' at
the end of the functions with the 'var'.

Relevant clippy warning: https://rust-lang.github.io/rust-clippy/master/index.html#needless_return
2019-02-05 21:39:38 +03:00
stratusjerry
7134885775 Spellcheck 2019-02-05 13:39:16 -05:00
ZapAnton
d445e3082a Fixed the 'unneeded_field_pattern' clippy warnings
This replaces all the occurrences of the Struct {field: _} with
the Struct { .. }.

Relevant clippy warning: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_field_pattern
2019-02-05 21:37:41 +03:00
ZapAnton
1a6840280b Fixed the 'ptr_arg' clippy warnings
This replaces all the occurrences of &<dynamic collection><T>
with the &[T].

Relevant clippy warning: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg
2019-02-05 21:22:16 +03:00
ZapAnton
6fb91ddfed Fixed the 'len_zero' clippy warnings
This replaces all the occurrences of the <collection>.len() == 0
with the <collection>.is_empty() and the occurrences of the
<collection>.len() > 0 with the !<collection>.is_empty()

Relevant clippy warning: https://rust-lang.github.io/rust-clippy/master/index.html#len_zero
2019-02-05 20:54:49 +03:00
ZapAnton
57e2beef3a Fixed the 'useless_format' clippy warning
This replaces all the occurrences of the format!(<&str>) with the <&str>.to_string()

Relevant clippy warning: https://rust-lang.github.io/rust-clippy/master/index.html#useless_format
2019-02-05 20:48:50 +03:00
Windel Bouwman
7941480fca Merge pull request #269 from mrecachinas/add-int-doc
Add int.__doc__ (addresses #261)
2019-02-05 18:26:28 +01:00
Windel Bouwman
0f0ceeaa00 Merge pull request #332 from lausek/imports
raise ImportError in import list
2019-02-05 18:25:41 +01:00
Windel Bouwman
fa91cc36e8 Merge pull request #329 from ZapAnton/int_invert
int type: Added __invert__
2019-02-05 18:14:21 +01:00
Windel Bouwman
e481063ca6 Fixed duplicate os error. 2019-02-05 18:13:08 +01:00
Windel Bouwman
815dd0937a Merge pull request #309 from holygits/add-os-error
Add OSError
2019-02-05 17:59:14 +01:00
Windel Bouwman
676f60296d Merge pull request #330 from ichyo/string-len
Use the number of characters instead of bytes for str.__len__
2019-02-05 17:57:58 +01:00
Windel Bouwman
8e006274ed Merge pull request #325 from rmliddle/implement-io
Factored OS Module for Windows Support, Unsafe Handling of Raw FileHandles and Descriptors
2019-02-05 17:49:52 +01:00
Windel Bouwman
b710eedb04 Merge pull request #324 from veera83372/refactor-py
Refactored: whats_left_to_implement.py
2019-02-05 17:45:10 +01:00
lausek
f4af599167 added ImportError as builtin 2019-02-05 17:41:05 +01:00
Timur Makarchuk
c7e6935e1c Get rid of exp usages
Assuming `exp` function was missing for platform-dependant reasons, let's try to test it with `sin` instead
2019-02-05 19:21:31 +03:00
Adam
6ea784e78e Merge pull request #323 from vokar97/handle-index-overflow
Add error handling for objsequence and objstr index overflow (addresses #276)
2019-02-05 16:00:07 +00:00
Adam
aee5090bd2 Merge pull request #321 from HomerMcMillan/tuple_comparisons
Fix error messages in tuple/list comparisons
2019-02-05 15:54:54 +00:00
ichyo
d1b034e3b9 Avoid using \xhh for string 2019-02-05 23:54:39 +09:00
lausek
f8db0f1c94 raise ImportError in import list 2019-02-05 15:42:39 +01:00
ichyo
fc779c2e3a Use the number of characters instead of bytes for str.__len__ 2019-02-05 23:26:13 +09:00
lausek
3d07ecdd1c int type: trunc and index 2019-02-05 14:08:08 +01:00
ZapAnton
8c469a6466 int type: Added tests for the __invert__ 2019-02-05 15:25:07 +03:00
ZapAnton
5db2025dec int type: Added __invert__ 2019-02-05 15:20:17 +03:00
rmliddle
aa2dff4bd9 Format os.rs 2019-02-05 23:08:45 +11:00
rmliddle
86e94f587b Comment fix and use of i64 instead of i32 2019-02-05 22:47:33 +11:00
lausek
73ae085ed8 implemented rounding funcs for int (#304) 2019-02-05 12:47:30 +01:00
rmliddle
eca75b3611 Comment and formatted on windows rust_file call 2019-02-05 22:18:24 +11:00
Ryan Liddle
0daa03875c windows fixes for os module 2019-02-05 22:14:14 +11:00
veera venky
ea4059a18f Refactored: whats_left_to_implement.py 2019-02-05 16:04:01 +05:30
rmliddle
ca815baeaf Factored out unix dependency 2019-02-05 20:57:06 +11:00
Vladimir Karamyshev
ebbd3d9f22 Add error handling for objsequence and objstr index overflow 2019-02-05 10:17:43 +03:00
coolreader18
de3762cabf Add .run(); fix .addToScope(); add panic-catcher for debugging 2019-02-05 00:39:16 -06:00
Homer McMillan
7446a52c18 Fix error messages in tuple/list comparisons 2019-02-05 00:27:36 -05:00
Windel Bouwman
63c83086c7 Merge pull request #320 from HomerMcMillan/tuple_comparisons
Tuple comparisons
2019-02-05 06:24:30 +01:00
Windel Bouwman
ed53a353c2 Merge pull request #316 from OddCoincidence/range-use-bigint
Represent range with BigInts
2019-02-05 06:21:04 +01:00
Windel Bouwman
2be174050a Merge pull request #305 from veera83372/master
Adding int.__bool__ method
2019-02-05 06:19:26 +01:00
Windel Bouwman
aea929a284 Merge pull request #319 from holygits/fix-fileno
Revert 'file_no' -> 'fileno' attr naming
2019-02-05 06:18:30 +01:00
Homer McMillan
fb58ca3e6c Add comparison tests for tuple 2019-02-04 23:31:39 -05:00
Homer McMillan
696bf8e9a9 rustfmt 2019-02-04 23:27:45 -05:00
Homer McMillan
608a13eabb Add comparison operations for tuple 2019-02-04 23:26:16 -05:00
holygits
5cad1b0215 Revert 'file_no' -> 'fileno' attr naming 2019-02-05 16:39:22 +13:00
coolreader18
f7c91c7df0 Add add_to_scope() method for WASM VM 2019-02-04 20:36:19 -06:00
Joey Hain
9ac8e55695 Represent range with BigInts 2019-02-04 17:38:23 -08:00
coolreader18
3bec2260bb Rename VMStore 2019-02-04 18:58:53 -06:00
holygits
9a37825f7b Add OSError
Fix heirarchy or existing os errors
2019-02-05 10:29:36 +13:00
veera venky
d3fedecd61 Adding 'int.__bool__' method 2019-02-05 02:26:44 +05:30
Windel Bouwman
f4a78d4148 Merge pull request #307 from veera83372/object-methods
Added object expected methods to left to implement list
2019-02-04 21:49:19 +01:00
Windel Bouwman
b7b4a8a51b Merge branch 'master' into add-int-doc 2019-02-04 21:47:09 +01:00
Windel Bouwman
47d43a7fef Merge pull request #306 from HomerMcMillan/range-builtin
Add built in range type (addresses #294)
2019-02-04 21:46:07 +01:00
Windel Bouwman
1c07a2285d Merge pull request #268 from mrecachinas/add-bool-doc
Add bool.__doc__ (addresses #260)
2019-02-04 21:34:58 +01:00
HomerMcMillan
41d73c49a1 Merge branch 'master' into range-builtin 2019-02-04 15:14:43 -05:00
veera venky
c8f2515f4b Added object expected methods to left to implement list 2019-02-05 01:42:32 +05:30
Homer McMillan
64bd33e787 Add built in range type (addresses #294) 2019-02-04 15:08:13 -05:00
Michael Recachinas
9dded0cb7b Replace context.new_property with context.new_str for int.__doc__ 2019-02-04 19:46:58 +00:00
Michael Recachinas
804def1522 Replace context.new_property with context.new_str for bool.__doc__ 2019-02-04 19:37:24 +00:00
Timur
b25aab006e Add type conversion to functions calls in math 2019-02-04 22:22:18 +03:00
Windel Bouwman
2b22cd443e Implement clippy thoughts into rustpython_parser 2019-02-04 18:18:40 +01:00
Windel Bouwman
7096434f95 Implement some clippy tips 2019-02-04 17:17:54 +01:00
Windel Bouwman
55aa12b68f Merge pull request #299 from holygits/fix-unicode-handling
Handle unicode string slicing with graphemes
2019-02-04 13:48:41 +01:00
Windel Bouwman
b7f6db753f Merge branch 'master' into fix-unicode-handling 2019-02-04 08:39:21 +01:00
Windel Bouwman
4242b66992 Merge pull request #301 from mrnugget/remove_dereference
Remove unnecessary dereferences/references in compiler
2019-02-04 08:37:32 +01:00
Windel Bouwman
1e576b5baa Merge pull request #273 from skinny121/tuple_add
Add tuple.__add__
2019-02-04 08:27:41 +01:00
Thorsten Ball
0146e5f51c Remove unnecessary dereferences/references in compiler
It's not necessary to dereference a reference to then take a reference
again, at least not in these cases, so we can remove them.
2019-02-04 08:15:22 +01:00
Windel Bouwman
caac5a34d5 Merge branch 'master' into tuple_add 2019-02-04 08:05:07 +01:00
Windel Bouwman
44e9658f52 Merge pull request #297 from HomerMcMillan/issue_295
Fix panic on out of bounds negative index (addresses #295)
2019-02-04 07:48:17 +01:00
Windel Bouwman
235aa864f4 Merge pull request #296 from agude/int_conj
Add .conjugate() method to int type
2019-02-04 07:43:13 +01:00
Windel Bouwman
371f8f81dc Merge pull request #298 from idbentley/alphebetize_exceptions
Alphebetize exception related code
2019-02-04 07:42:42 +01:00
holygits
33a3ec8832 Handle unicode string slicing with graphemes 2019-02-04 15:40:30 +13:00
idbentley
f2db23bb35 correct order of errors. 2019-02-03 16:51:17 -05:00
Homer McMillan
055e577424 Fix panic on out of bounds negative index (addresses #295)
Also an out of bounds index now raises an IndexError rather than a ValueError
2019-02-03 16:38:04 -05:00
idbentley
19557e8344 Alphebetize exception related code 2019-02-03 16:36:25 -05:00
Alexander Gude
33523d492c Change int.conjugate() to return a new int
This results in the correct behavior (that is, matching CPython) for
both int and bool types.

Also adding a bool conjugate test.
2019-02-03 13:31:09 -08:00
Windel Bouwman
0f87d151a0 Merge pull request #289 from chaconnewu/198fix
Fix reverse method for calling div.
2019-02-03 21:27:59 +01:00
Windel Bouwman
7c6fdbacf1 Merge pull request #279 from HomerMcMillan/list-orderable-ops
Add list.{__lt__, __gt__, __le__, __ge__}
2019-02-03 21:25:35 +01:00
Alexander Gude
a95747f161 Add .conjugate() method to int type
Also add tests for for the int type, and a commented out one for the
bool type.
2019-02-03 11:18:23 -08:00
Matthew Constable
190b2a43d9 Fixed formatting 2019-02-03 18:34:35 +00:00
Matthew Constable
0beceefd0c Add a few tests for sets which reflect new changes. 2019-02-03 17:51:06 +00:00
Matthew Constable
da5046100b Able to create set from iterable. 2019-02-03 17:25:24 +00:00
Matthew Constable
b433b7fcf0 Implemented remove() method on set. 2019-02-03 17:01:32 +00:00
Homer McMillan
353d881bac Fix missing seq_mul import 2019-02-03 11:33:11 -05:00
HomerMcMillan
168e0e5471 Merge branch 'master' into list-orderable-ops 2019-02-03 11:17:09 -05:00
Matthew Constable
c022ac46e6 Refactored adding to set using hash into helper function. 2019-02-03 16:09:44 +00:00
Matthew Constable
6acb7eb006 Handle attempt to add non-hashable items to a set. 2019-02-03 15:46:13 +00:00
Matthew Constable
d5801162bd Sets use python __hash__ functions when items are added - need to re-implement set creation from iterable 2019-02-03 15:25:24 +00:00
Windel Bouwman
34c99b0c99 Merge pull request #278 from holygits/improve-fio-errs
Better error handling for file io
2019-02-03 16:03:41 +01:00
Yu Wu
38ee8aeed6 Fix reverse method for calling div. 2019-02-03 07:02:36 -08:00
Windel Bouwman
384ae474de Merge pull request #282 from orf/use-xdg
Use XDG paths to store Python history
2019-02-03 15:40:24 +01:00
Windel Bouwman
a7d011f9c7 Merge pull request #270 from ZapAnton/str_isdecimal
Added the isdecimal method to the 'str' class
2019-02-03 15:37:20 +01:00
Windel Bouwman
ac0ea87ead Merge pull request #271 from holygits/bitshift
Implement `__rshift__` and `__lshift__` for integer type
2019-02-03 15:35:50 +01:00
Windel Bouwman
00f86d1454 Merge pull request #288 from 11Takanori/fix-typo
Fix typo
2019-02-03 14:58:24 +01:00
Takanori Ishibashi
334d78704a distuingish -> distinguish 2019-02-03 21:41:04 +09:00
Windel Bouwman
3bc9232eeb Merge pull request #272 from ZapAnton/fix_readme_testing
README: Clarified the 'Testing' section
2019-02-03 12:27:56 +01:00
Windel Bouwman
cdcddcc6c6 Merge pull request #281 from chaconnewu/198
Use call_or_unsupported for operators.
2019-02-03 11:50:09 +01:00
Windel Bouwman
1d7149e131 Merge pull request #280 from HomerMcMillan/list-pop
Add list.pop
2019-02-03 11:49:01 +01:00
Tom Forbes
a72dbf1d0c Use XDG paths to store Python history 2019-02-03 10:07:50 +01:00
Windel Bouwman
38bf2dde3d Merge pull request #274 from skinny121/tuple_mul
Add tuple.__mul__
2019-02-03 08:05:20 +01:00
Windel Bouwman
37e9f98859 Merge pull request #277 from 0xflotus/patch-1
fixed small errors
2019-02-03 08:02:21 +01:00
Homer McMillan
7b27fbf369 Add list.pop
Also include IndexError in the __builtin__ module.
2019-02-03 00:49:52 -05:00
Yu Wu
561eb8ed4f Use call_or_unsupported for operators. 2019-02-02 21:47:28 -08:00
Homer McMillan
8852435a3d Run cargo fmt 2019-02-02 23:05:32 -05:00
Homer McMillan
2b74727783 Fix broken test 2019-02-02 22:41:34 -05:00
Homer McMillan
ea1a7bb395 Add list.{__lt__, __gt__, __le__, __ge__} 2019-02-02 22:04:26 -05:00
holygits
8854430651 Better error handling for file io
Add FileNotFoundError
Add PermissionError
Minor idomatic clean ups
2019-02-03 14:53:21 +13:00
0xflotus
167aefa829 Update builtins.md 2019-02-03 02:35:05 +01:00
0xflotus
dae5b146ff fixed converter 2019-02-03 02:30:58 +01:00
ben
8f9b733a77 Add tuple.__mul__ 2019-02-03 13:59:43 +13:00
holygits
e8d1e10226 Implement __rshift__ and __lshift__ for integer 2019-02-03 12:38:38 +13:00
ZapAnton
8558b84b16 README: Replaced the 'pipenv shell' and the 'pytest -v' commands with the single 'pipenv run pytest -v' command in the 'Testing' section 2019-02-03 02:19:59 +03:00
ZapAnton
b55150c7bd README: Added the 'pipenv install' command to the 'Testing' section 2019-02-03 02:15:57 +03:00
ZapAnton
23de5581bd Added tests for the isdecimal method 2019-02-03 02:05:57 +03:00
ZapAnton
46b939721f str: Added the isdecimal method 2019-02-03 01:51:47 +03:00
Michael Recachinas
e557ff290a Suppress warning and rename obj to _zelf in arg_check 2019-02-02 21:39:06 +00:00
Michael Recachinas
f0abcff53d Add int.__doc__ (addresses #261) 2019-02-02 21:37:49 +00:00
Michael Recachinas
e0b41d1386 Add bool.__doc__ (addresses #260) 2019-02-02 21:25:14 +00:00
ben
b13b4741ad Add tuple.__add__. Also stop rustfmt from trying to format generated parser. 2019-02-02 17:40:17 +13:00
coolreader18
f47864f0ac Return Ok(()) from destroy() 2019-01-31 16:33:11 -06:00
coolreader18
136a476cd8 Call assert_valid() in destroy() 2019-01-31 16:13:55 -06:00
coolreader18
b32b732abe Run cargo fmt 2019-01-30 14:35:00 -06:00
coolreader18
d0a4f9d7f5 Make destroy() method public 2019-01-30 12:40:08 -06:00
coolreader18
f064bcaf57 Add ids() function to VMStore and destroy() method to VirtualMachine 2019-01-30 12:33:32 -06:00
coolreader18
13b2f83084 Fix vms.get() 2019-01-30 12:30:56 -06:00
coolreader18
4020ee7d41 Add a bare-bones VirtualMachine class to the WASM library 2019-01-30 12:18:59 -06:00
Windel Bouwman
328f81a28e Merge pull request #266 from coolreader18/format-mk-module
Format module building in a more readable way
2019-01-30 18:09:17 +01:00
Windel Bouwman
892493e464 Rename PyObjectKind into PyObjectPayload 2019-01-30 18:06:27 +01:00
coolreader18
37b5669bed Fix syntax error 2019-01-30 10:13:55 -06:00
coolreader18
f193291471 Merge branch 'master' into format-mk-module 2019-01-30 10:09:47 -06:00
Windel Bouwman
31523fe4d7 Merge pull request #265 from rmliddle/implement-io
File-IO: IO Module and Open Builtin
2019-01-29 20:43:28 +01:00
rmliddle
deb0688a99 Changed buffer imp. to use type + removed ByteArray Kind 2019-01-29 18:40:40 +11:00
coolreader18
e9bfea834a Format module building in a more readable way 2019-01-28 23:02:43 -06:00
Windel Bouwman
d627230434 Merge pull request #263 from coolreader18/string-str
Remove unnecessary to_string conversions
2019-01-28 20:38:54 +01:00
Windel Bouwman
d365563010 Merge pull request #264 from coolreader18/fix-trim-warnings
Fix warnings from using trim_left and trim_right
2019-01-28 20:36:06 +01:00
rmliddle
0ee535e49a Removed append + create 2019-01-28 20:14:19 +11:00
rmliddle
3ce9972c9c removed os.O_NONBLOCK from snippet 2019-01-28 20:07:57 +11:00
rmliddle
507f7bdca9 Fix for os open (optional params not allowed) 2019-01-28 19:38:06 +11:00
rmliddle
c011db2819 fmt w/nightly 2019-01-28 19:21:27 +11:00
rmliddle
7b23d0e917 rust fmt 2019-01-28 18:54:50 +11:00
rmliddle
9a86bbd718 ByteArray Usage 2019-01-28 18:30:19 +11:00
coolreader18
989357fe81 Fix warnings from using trim_left and trim_right 2019-01-27 23:02:27 -06:00
coolreader18
5ecff1b37e Remove unnecessary to_string conversions 2019-01-27 21:45:21 -06:00
rmliddle
c2e73cc829 Test Snippets for buffered_read, open builtin 2019-01-23 19:16:03 +11:00
rmliddle
9efc68efcb Generalized Mode Handling 2019-01-22 21:59:10 +11:00
rmliddle
dda3d7ffb7 Bug fix for sequential Writes, New File Writes 2019-01-21 20:03:36 +11:00
rmliddle
3845e23881 -Logging length in FileIO write, +Bytes to String in TextIOBase 2019-01-19 14:13:12 +11:00
rmliddle
b54738978a Remaining IO open classes: TextBaseIO, TextWrapperIO 2019-01-17 21:20:31 +11:00
rmliddle
30165f6c8a open builtin 2019-01-16 20:16:56 +11:00
rmliddle
edc720e79f Buffered Objects for Open 2019-01-14 20:32:27 +11:00
rmliddle
2bbd4fd18f BufferedIOBase Read 2019-01-13 10:54:47 +11:00
Windel Bouwman
ade4c88d90 Merge pull request #256 from RustPython/fix-deployment-again
Fix the deploy condition for missing spaces around equals sign
2019-01-12 22:44:38 +01:00
Windel Bouwman
e41b9179f5 Merge pull request #254 from RustPython/list_index
Added list.index()
2019-01-12 10:25:42 +01:00
Shing Lyu
83f05c6448 Fix the deploy condition for missing spaces around equals sign 2019-01-10 22:09:33 +01:00
Shing Lyu
5e8eb8a001 Added list.index() 2019-01-10 22:01:42 +01:00
Windel Bouwman
ce36919fe3 Merge pull request #255 from adamchainz/patch-1
Update example
2019-01-10 20:27:51 +01:00
Adam Johnson
32a58f8897 Update example
Improve spelling, grammar, and HTML a bit on the example page.
2019-01-10 14:07:08 +00:00
Windel Bouwman
cab2e0d076 Merge pull request #250 from RustPython/fix-deploymnet
Limit the deployment only to the specific build job
2019-01-09 16:36:46 +01:00
rmliddle
5e1324fd23 os modes 2019-01-09 20:56:08 +11:00
Shing Lyu
7c8ebee43b Limit the deployment only to the specfic build job 2019-01-08 22:37:31 +01:00
rmliddle
9041129bb8 read_into on FileIO 2019-01-08 18:10:35 +11:00
rmliddle
6deb71d84f os.open impl 2019-01-08 12:14:43 +11:00
rmliddle
dc6238bb0c __offset__ workaround 2019-01-05 21:38:33 +11:00
rmliddle
b783657477 file_io_readinto implementation for fixed length buffer reads 2019-01-04 19:35:33 +11:00
rmliddle
15d0c39c81 fixes to bytearray len 2019-01-04 19:34:28 +11:00
Windel Bouwman
6d0a25fb1c Merge pull request #248 from coolreader18/dockerfile
Create dockerfiles for the rustpython binary and wasm demo
2019-01-03 19:26:38 +01:00
coolreader18
3e3d28fa1d Create dockerfiles for the rustpython binary and wasm demo 2019-01-02 18:57:27 -06:00
rmliddle
cbd8d7b171 len attributes on byte types 2019-01-03 08:16:04 +11:00
Windel Bouwman
a28b665396 Merge pull request #246 from rmliddle/bytes-representation
Bytes representation changed from hex to utf-8
2019-01-02 22:07:21 +01:00
rmliddle
3d6742a9e8 change to bytes repr 2019-01-02 21:25:48 +11:00
rmliddle
278e1a8298 method name change for fileio 2019-01-02 13:41:12 +11:00
rmliddle
08a9fd9819 memoryview object, FileIO Methods 2019-01-01 23:39:21 +11:00
Windel Bouwman
d508d130b6 Merge pull request #235 from xrmx/stringconstants
Implement most string module constants
2018-12-29 15:29:28 +01:00
Windel Bouwman
d425c26763 Merge pull request #245 from coolreader18/final-demo-improvements
Final demo improvements
2018-12-29 15:28:26 +01:00
coolreader18
231e3f2f16 Export PyEvalOptions in typescript defs 2018-12-28 21:57:41 -06:00
coolreader18
e65639f61a Remove yarn.lock 2018-12-28 21:43:13 -06:00
coolreader18
d7fdc5c177 Fix typescript hack 2018-12-28 14:42:43 -06:00
coolreader18
36997e12d9 Comment out WB's TS definitions using a hack 2018-12-28 14:35:45 -06:00
coolreader18
1d5df4130a Add doc comments and typescript custom section 2018-12-27 22:31:15 -06:00
coolreader18
b2772804f2 Add README and manifest fields for the WASM library 2018-12-27 21:06:59 -06:00
coolreader18
4cc7f5aa9c Merge #console and #code styles 2018-12-27 20:43:09 -06:00
coolreader18
1f02cc0fa3 Squash all demo commits onto one branch 2018-12-27 20:28:12 -06:00
Riccardo Magliocchetti
e4ca1655e9 Implement most string module constants
whitespace and thus printable are excluded because i haven't found
a way to make tests pass.
2018-12-27 23:48:11 +01:00
Windel Bouwman
4c5b5845bb Merge pull request #244 from coolreader18/boxed-rustfunc
Change RustPyFunc from a fn pointer to a Fn trait
2018-12-27 20:23:22 +01:00
AgentMacklin
79a3b13252 Implement most of the string methods. (#239)
* implemented more functions

* backup

* Improve demo site

* Formatting; move the `+ '\n'` hack to eval().

* Rename run_code() to run_from_textbox()

* Switch to using json.dumps for py_to_js()

* Clarify names of wasm builtins

* Remove dependency on num_bigint

* Allow injecting JS variables into python with eval_py()

eval_py(`return js_vars["a"]`, { a: 9 }) == 9

* dict() now should work properly

e.g.
``` dict(a=2, b=3) == {"a": 2, "b": 3} ```

* Add documentation for eval_py() and update error message handling

Also, switch from iterating over the values of js_injections and
serializing each of them individually to asserting it's an object and
then just stringifying the whole thing.

* Finish revamping `dict_new()`

* Add 'from x import *' syntax.

This is a separate opcode in CPython so I added it as such here.

* Add test for dicts

* added functions

* ran rustfmt and fixed isidentifier

* fixed zfill and make_title

* python3.6 doesn't contain isascii()
2018-12-27 20:22:04 +01:00
coolreader18
8303743aab Remove RustPyFunc trait, just use Fn(..) everywhere 2018-12-27 11:50:14 -06:00
coolreader18
09602a2ec6 Change RustPyFunc from a fn pointer to a Fn trait 2018-12-27 09:18:00 -06:00
Windel Bouwman
f325ef1499 Merge pull request #240 from coolreader18/json-error
Have the json ser/de functions throw an exception instead of panicking
2018-12-27 09:20:52 +01:00
Windel Bouwman
978e7eabe3 Merge pull request #241 from coolreader18/formatted-exceptions
Format exceptions nicely (no more RefCell { value: .. }!)
2018-12-27 09:14:35 +01:00
coolreader18
8fee5a8800 Run cargo fmt --all 2018-12-27 00:12:08 -06:00
coolreader18
396842ef9d Readd conflicting files 2018-12-27 00:04:20 -06:00
coolreader18
dfadd03f95 Remove (now outdated) previously conflicting files 2018-12-27 00:02:33 -06:00
coolreader18
ada92d33a3 Add conflicting files 2018-12-27 00:01:20 -06:00
coolreader18
2968982a8f Change README portion for compiling wasm 2018-12-26 23:51:28 -06:00
coolreader18
877206dc47 Switch from shell to npm scripts for demo using webpack and @wasm-tool/wasm-pack-plugin
Also change travis deploy to use new demo directory.
2018-12-26 23:34:51 -06:00
coolreader18
0ac0432a53 Run cargo fmt 2018-12-26 18:23:40 -06:00
coolreader18
80573b0544 Format PyObject's correctly and nicely 2018-12-26 18:09:49 -06:00
coolreader18
d1a584f0fd Don't allocate a new string for each new type for the ExceptionZoo 2018-12-26 14:19:19 -06:00
coolreader18
a77b7e0ce4 Have json.* throw an exception instead of panicking 2018-12-26 14:18:15 -06:00
coolreader18
c38796bb49 Add some documentation for functions on the demo site 2018-12-26 13:25:56 -06:00
coolreader18
94d6a91873 Fix js_to_py with JS undefined 2018-12-26 13:21:29 -06:00
coolreader18
e0959b9384 Implement error conversion for js_to_py 2018-12-26 11:21:45 -06:00
coolreader18
132930ec82 Allow passing closures from JS to python via vars 2018-12-26 01:59:15 -06:00
coolreader18
63b3f3e71b Fix blanket impl of RustPyFunc 2018-12-24 15:51:54 -06:00
coolreader18
d1d958516d Change the instances of Fn(..) -> PyResult to a RustPyFunc trait alias 2018-12-24 15:45:45 -06:00
coolreader18
ffcd40b435 Remove conflicting files 2018-12-24 15:35:50 -06:00
coolreader18
24507de3b1 Re-add conflicting files 2018-12-24 15:34:52 -06:00
coolreader18
ab23f2c940 Use str.format for the demo 2018-12-24 15:28:49 -06:00
coolreader18
840c5072fb Improve UX for demo 2018-12-24 15:28:49 -06:00
coolreader18
d54d2b1c03 Make scripts executable 2018-12-24 15:28:49 -06:00
coolreader18
2ea9dca40c Add example, change some stuff in the demo to align with example 2018-12-24 15:28:49 -06:00
coolreader18
ca30ebcf5d Genericize the wasm lib to not be specifically for the demo
This included changing RustObjectKind::RustFunction.function to be
a `Box<Fn()>` instead of a `fn()` to support closures.
2018-12-24 15:28:49 -06:00
coolreader18
4c32693c7b Switch to using one workspace, move profile to root Cargo.toml 2018-12-24 15:28:49 -06:00
Windel Bouwman
946df53077 Merge pull request #237 from johndaniels/add-star-import
Add 'from x import *' syntax.
2018-12-23 17:55:34 +01:00
Gitea
ac3da8b453 Add 'from x import *' syntax.
This is a separate opcode in CPython so I added it as such here.
2018-12-22 22:40:02 -05:00
Windel Bouwman
366f3e2b13 Merge pull request #236 from coolreader18/proper-dict
Make `dict()` work like it does in cpython
2018-12-22 16:05:31 +01:00
coolreader18
427ce4347e Add test for dicts 2018-12-22 00:04:13 -06:00
coolreader18
f1784236af Finish revamping dict_new() 2018-12-21 23:35:45 -06:00
Shing Lyu
71ba5019bf Merge pull request #230 from coolreader18/master
Improve wasm demo website
2018-12-21 16:22:34 +01:00
coolreader18
e77f223538 Add documentation for eval_py() and update error message handling
Also, switch from iterating over the values of js_injections and
serializing each of them individually to asserting it's an object and
then just stringifying the whole thing.
2018-12-18 19:03:04 -06:00
coolreader18
03c619f79e Rearrange website directory and change webpack config 2018-12-18 18:22:30 -06:00
coolreader18
bdc80dc75b dict() now should work properly
e.g.
``` dict(a=2, b=3) == {"a": 2, "b": 3} ```
2018-12-18 01:34:00 -06:00
Windel Bouwman
950dbd1a77 Use new_list when constructing multiplied list. 2018-12-17 12:14:29 +01:00
Windel Bouwman
bbe333d6c7 Merge pull request #233 from rossjones/232-impl-mul-for-list
Implements __mul__ for lists
2018-12-17 11:55:44 +01:00
Windel Bouwman
8aaadb16c0 Merge pull request #234 from johndaniels/indentation
Handle mixed spaces and tabs.
2018-12-17 11:55:20 +01:00
Windel Bouwman
1b13b0c4e2 Merge pull request #231 from johndaniels/format
Add format builtin and String formatting stuff.
2018-12-17 11:50:14 +01:00
Gitea
9468b657d2 Run cargo fmt. 2018-12-16 17:40:25 -05:00
Gitea
c74cd90d8e Handle mixed spaces and tabs.
This allows the parser to handle tabs and spaces. Currently it
requires that spaces come after any tabs, which is slightly more
strict than python3. It also requires that neighboring indentation
levels have either both more spaces and tabs or less spaces and
tabs so that tab size can't make perception of indentation
differ from what the parser interprets.

I didn't opt to implement PartialOrd on IndentationLevel because I
wasn't sure that the comparison logic would meet the logical
requirements for that trait. One could easily switch to having it
implement PartialOrd though. This would necessitate switching to
manually implementing PartialEq so that it's behavior 'matches'.
It's unclear from the docs what 'matches' exactly means so for
now I'm avoiding implementing the traits.
2018-12-16 17:11:37 -05:00
Gitea
95d4073dd8 Add newline to end of file.
The parser currently doesn't handle missing newline gracefully.
2018-12-16 16:21:40 -05:00
Gitea
a6288acd22 Cargo format. 2018-12-16 15:48:59 -05:00
Gitea
bbe4844f6c Fix snippet to not use tab.
We should add support for '\t', but that should probably be a separate ticket.
2018-12-16 15:43:07 -05:00
Ross Jones
ae2f7ed1cb Implements __mul__ for lists
Implements __mul__ for lists so that it is possible to do things like

```
s = [1, 2,] * 3
s == [1, 2, 1, 2, 1, 2]
```
2018-12-16 12:22:31 +00:00
Gitea
b726e675ff Add format builtin and String formatting stuff.
This includes everything needed to call str.format with integers
as positional and keyword parameters.
2018-12-15 19:46:09 -05:00
coolreader18
a796b134a5 Allow injecting JS variables into python with eval_py()
eval_py(`return js_vars["a"]`, { a: 9 }) == 9
2018-12-15 12:20:03 -06:00
coolreader18
e78a25132e Remove dependency on num_bigint 2018-12-15 11:38:08 -06:00
coolreader18
3be6fee737 Clarify names of wasm builtins 2018-12-15 11:36:53 -06:00
coolreader18
921efd4d14 Switch to using json.dumps for py_to_js() 2018-12-15 11:33:37 -06:00
coolreader18
2ae1df590e Rename run_code() to run_from_textbox() 2018-12-15 01:41:25 -06:00
coolreader18
f8cce25f69 Formatting; move the + '\n' hack to eval(). 2018-12-15 01:31:44 -06:00
coolreader18
b428f2e3b3 Improve demo site 2018-12-15 00:49:47 -06:00
Windel Bouwman
62c53d8e5d Try to make it simpler to switch dict storage types. 2018-12-13 20:38:09 +01:00
Windel Bouwman
521f664e16 Merge pull request #229 from AgentMacklin/master
Added some of the missing str methods
2018-12-13 20:31:45 +01:00
Austen LeBeau
7ac22d96d1 update and added more functions 2018-12-13 12:02:18 -06:00
Windel Bouwman
a29e882bc1 Store dict key as pyobject into hashmap. 2018-12-13 17:05:01 +01:00
Windel Bouwman
e657633e51 Move set_item to context struct. 2018-12-12 22:27:28 +01:00
Windel Bouwman
4095e0cad7 Modify location of set_attr so that we are able to create str python objects for the dictionary. 2018-12-12 22:06:19 +01:00
Windel Bouwman
31f50eda3d Merge pull request #226 from RustPython/demo-error
[WASM] Catch errors and show it in the standard output textarea
2018-12-12 20:01:31 +01:00
Windel Bouwman
0215830aaa Move set_attr and set_item to context. 2018-12-12 19:41:09 +01:00
Austen LeBeau
dd2b4e3c25 added isalnum, isalpha, isdigit, swapcase 2018-12-12 12:01:35 -06:00
Windel Bouwman
5c04ad8aae Make underlying dict type more hidden. 2018-12-12 15:13:40 +01:00
Austen LeBeau
07336fa984 initial fork commit 2018-12-11 22:44:56 -06:00
Shing Lyu
6021fca8cd [WASM] Print the Rust panic to the output textarea 2018-12-11 21:50:25 +01:00
Shing Lyu
fabc67985a Make the run button bigger so it doesn't overflow 2018-12-11 21:38:02 +01:00
Windel Bouwman
95092be36d Merge pull request #225 from RustPython/test-demo
Fixed the travis build for deploying the demo page
2018-12-11 20:22:13 +01:00
Shing Lyu
0159051e95 Updated README about WASM build 2018-12-10 23:13:54 +01:00
Shing Lyu
13a9922d93 Fix the demo page travis build 2018-12-10 23:07:15 +01:00
Windel Bouwman
b46fc938d4 Merge pull request #224 from RustPython/readme-demo
Update README, adding demo and instruction for how to update doc
2018-12-10 22:18:37 +01:00
Shing Lyu
160cfe6155 Added link to online demo in README 2018-12-10 21:58:43 +01:00
Windel Bouwman
8345acc402 Change rustfmt check to stable. 2018-12-10 21:33:23 +01:00
Shing Lyu
bb4454912e Added instruction on updating online doc and demo page 2018-12-10 20:45:12 +01:00
Windel Bouwman
69d21e0ebb Merge pull request #222 from RustPython/wasm-output-pure-rs
[WASM] Print STDOUT to textarea on the demo page
2018-12-09 22:13:00 +01:00
Shing Lyu
b2aa7ac2fb [WASM] Changed the demo to fibonacci calculation 2018-12-09 21:35:23 +01:00
Shing Lyu
3e231620cd [WASM] Print STDOUT to textarea in HTML 2018-12-09 21:35:23 +01:00
Windel Bouwman
f8f9fa7fd0 Merge pull request #217 from RustPython/travis-demo
CI build and deploy demo page on master branch
2018-12-07 10:15:50 +01:00
Shing Lyu
b5c1990267 CI build and deploy demo page on master branch 2018-12-06 20:35:53 +01:00
Windel Bouwman
351a61f2b3 Merge pull request #216 from RustPython/forkme
Added fork me on github ribbon to demo page
2018-12-05 11:30:58 +01:00
Windel Bouwman
34a60ce6a2 Merge pull request #218 from RustPython/stabledoc
Use stable rust to build documentation
2018-12-05 11:30:38 +01:00
Shing Lyu
41d5dc52eb Use stable rust to build documentation 2018-12-04 21:15:51 +01:00
Shing Lyu
71ea9b8f16 Added fork me on github ribbon to demo page 2018-12-04 20:58:00 +01:00
Windel Bouwman
fa89e8803c Merge pull request #214 from RustPython/online-demo
Created a demo page so user can try their code online
2018-12-04 09:12:07 +01:00
Windel Bouwman
30bb111b1a Merge pull request #208 from RustPython/travis-fix
Limit the gh-pages deployment step to only nightly build
2018-12-04 09:01:16 +01:00
Shing Lyu
8d78c67d0b Created a demo page so user can try their code online 2018-12-03 20:49:26 +01:00
Shing Lyu
5734fc29ca Merge pull request #203 from RustPython/consolelog
Mapping Python print to JavaScript console.log
2018-12-03 20:48:43 +01:00
Shing Lyu
03911d98d7 Limit the gh-pages deployment step to only nightly build 2018-12-03 20:03:05 +01:00
Shing Lyu
2c55c4793e [WASM] Mapping print to console.log 2018-12-03 19:51:48 +01:00
Windel Bouwman
8eacbcbc06 Add builtins to sys.modules. Add __float__ method to int class. 2018-11-26 22:31:40 +01:00
Windel Bouwman
f227ce0498 Add random module 2018-11-25 23:20:10 +01:00
Windel Bouwman
eb51007993 Merge pull request #206 from RustPython/travis-branch
Push website to the master branch to simplify website development
2018-11-25 22:18:14 +01:00
Windel Bouwman
1b4b157a2d Merge pull request #207 from yodalee/math-implementation-with-statrs
Math implementation with statrs
2018-11-25 22:05:41 +01:00
yodalee
68892fb4e2 fix rustfmt 2018-11-25 22:13:26 +08:00
yodalee
04548db1e0 add implementation of special math function
function include: erf, erfc, gamma, lgamma
use package statrs' implementation
2018-11-25 20:10:34 +08:00
Windel Bouwman
ee2fb20f96 Merge pull request #205 from RustPython/readme-update
Added link to documentation in README
2018-11-24 12:05:52 +01:00
Shing Lyu
de61b1c685 Push website to the master branch to simplify website development 2018-11-24 10:43:56 +01:00
Shing Lyu
51271e5000 Added link to documentation in README 2018-11-24 10:37:19 +01:00
Windel Bouwman
a8fb2f3754 Merge pull request #204 from RustPython/travis-doc
Auto build and deploy documentation to website repo
2018-11-23 18:32:44 +01:00
Shing Lyu
023e6119c4 Auto build and deploy documentation to website repo 2018-11-23 11:51:39 +01:00
Windel Bouwman
083eb977ad Merge pull request #202 from RustPython/cleanup
Removed unused wasm/src/main.rs file
2018-11-22 21:37:32 +01:00
Shing Lyu
c1ab263258 Removed unused wasm/src/main.rs file 2018-11-20 21:50:17 +01:00
Windel Bouwman
be462afaa4 Add method to list and tuple class. 2018-11-17 12:31:24 +01:00
Windel Bouwman
a17fb3f4d0 Merge pull request #197 from BojanKogoj/bojan/vm-call_or_unsupported
WIP: Added call_or_unsupported to vm.rs
2018-11-17 09:07:19 +01:00
Shing Lyu
cd3429ce4d Merge pull request #193 from RustPython/readme-typo
Fixed wasm-bindgen typo in README
2018-11-16 14:44:00 +01:00
Bojan
0da1f73777 Removed empty space 2018-11-16 07:49:12 +01:00
Bojan
d972b07195 Fixed method comment 2018-11-15 23:47:11 +01:00
Bojan
f9860d083e Moved and to use new method 2018-11-15 23:42:17 +01:00
Bojan
15c6328ecd Moved sub to use new method 2018-11-15 23:42:03 +01:00
Bojan
05d2faa227 Added call_or_unsupported to vm.rs
This is to prevent code duplication
2018-11-15 23:37:46 +01:00
Shing Lyu
bbdef3d8c8 Merge pull request #194 from RustPython/wasm-doc
Updated the wasm installation instruction
2018-11-15 16:57:07 +01:00
Shing Lyu
1a0677ab44 Updated the wasm installation instruction 2018-11-15 00:25:22 +01:00
Shing Lyu
2939e53717 Fixed wasm typos in README 2018-11-14 23:43:44 +01:00
370 changed files with 54983 additions and 11133 deletions

2
.dockerignore Normal file
View File

@@ -0,0 +1,2 @@
target
**/node_modules

View File

@@ -0,0 +1,16 @@
---
name: Report incompatibility
about: Report an incompatibility between RustPython and CPython
title: ''
labels: feat
assignees: ''
---
## Feature
<!-- What Python feature is missing from RustPython? Give a short description of the feature and how you ran into its absence. -->
## Python Documentation
<!-- Give a link to the feature in the CPython documentation (https://docs.python.org/3/) in order to assist in its implementation. -->

24
.github/ISSUE_TEMPLATE/rfc.md vendored Normal file
View File

@@ -0,0 +1,24 @@
---
name: RFC
about: Make a suggestion in a Request for Comments format to RustPython
title: "[RFC] "
labels: RFC
assignees: ''
---
## Summary
<!-- A quick overview of your suggestion -->
## Detailed Explanation
<!-- Elaborate on your suggestion in all its details -->
## Drawbacks, Rationale, and Alternatives
<!-- What drawbacks might this solution have? Why do you feel it is necessary? What other options might there be to solving this problem? -->
## Unresolved Questions
<!-- What would you like feedback on for fleshing out your suggestion? -->

6
.gitignore vendored
View File

@@ -1,8 +1,12 @@
/target
wasm/target
/*/target
**/*.rs.bk
**/*.bytecode
__pycache__
**/*.pytest_cache
.*sw*
.repl_history.txt
.vscode
wasm-pack.log
.idea/
tests/snippets/resources

View File

@@ -1,66 +1,116 @@
language: rust
rust:
- stable
- beta
- nightly
script:
- cargo build --verbose --all
- cargo test --verbose --all
env:
# This is used to only capture the regular nightly test in allow_failures
- REGULAR_TEST=true
cache: cargo
matrix:
include:
# To test the snippets, we use Travis' Python environment (because
# installing rust ourselves is a lot easier than installing Python)
- language: python
python: 3.6
cache:
pip: true
# Because we're using the Python Travis environment, we can't use
# the built-in cargo cacher
directories:
- /home/travis/.cargo
- target
env:
- TRAVIS_RUST_VERSION=stable
- REGULAR_TEST=false
script: tests/.travis-runner.sh
- language: python
python: 3.6
cache:
pip: true
# Because we're using the Python Travis environment, we can't use
# the built-in cargo cacher
directories:
- /home/travis/.cargo
- target
env:
- TRAVIS_RUST_VERSION=beta
- REGULAR_TEST=false
script: tests/.travis-runner.sh
- name: rustfmt
language: rust
rust: nightly
cache: cargo
before_script:
- rustup component add rustfmt-preview
script:
# Code references the generated python.rs, so put something in
# place to make `cargo fmt` happy. (We use `echo` rather than
# `touch` because rustfmt complains about the empty file touch
# creates.)
- echo > parser/src/python.rs
- cargo fmt --all -- --check
env:
- REGULAR_TEST=false
allow_failures:
- rust: nightly
env: REGULAR_TEST=true
fast_finish: true
include:
- name: Run rust tests
language: rust
rust: stable
cache: cargo
script:
- cargo build --verbose --all
- cargo test --verbose --all
env:
# Prevention of cache corruption.
# See: https://docs.travis-ci.com/user/caching/#caches-and-build-matrices
- JOBCACHE=1
# To test the snippets, we use Travis' Python environment (because
# installing rust ourselves is a lot easier than installing Python)
- name: python test snippets
language: python
python: 3.6
cache:
- pip
- cargo
env:
- JOBCACHE=2
- TRAVIS_RUST_VERSION=stable
- CODE_COVERAGE=false
script: tests/.travis-runner.sh
- name: Check rust code style with rustfmt
language: rust
rust: stable
cache: cargo
before_script:
- rustup component add rustfmt
script:
- cargo fmt --all -- --check
env:
- JOBCACHE=3
- name: publish documentation
language: rust
rust: stable
cache: cargo
script:
- cargo doc --no-deps --all
if: branch = release
env:
- JOBCACHE=4
deploy:
- provider: pages
repo: RustPython/website
target-branch: master
local-dir: target/doc
skip-cleanup: true
# Set in the settings page of your repository, as a secure variable
github-token: $WEBSITE_GITHUB_TOKEN
keep-history: true
- name: WASM online demo
language: rust
rust: stable
cache: cargo
install:
- nvm install node
# install wasm-pack
- curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
script:
- cd wasm/demo
- npm install
- npm run dist
if: branch = release
env:
- JOBCACHE=5
deploy:
- provider: pages
repo: RustPython/demo
target-branch: master
local-dir: wasm/demo/dist
skip-cleanup: true
# Set in the settings page of your repository, as a secure variable
github-token: $WEBSITE_GITHUB_TOKEN
keep-history: true
- name: Code Coverage
language: python
python: 3.6
cache:
- pip
- cargo
script:
- tests/.travis-runner.sh
# Only do code coverage on master via a cron job.
if: branch = master AND type = cron
env:
- JOBCACHE=6
- TRAVIS_RUST_VERSION=nightly
- CODE_COVERAGE=true
- name: test WASM
language: python
python: 3.6
cache:
- pip
- cargo
addons:
firefox: latest
install:
- nvm install node
- pip install pipenv
script:
- wasm/tests/.travis-runner.sh
env:
- JOBCACHE=7
- TRAVIS_RUST_VERSION=stable

1797
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,29 @@
[package]
name = "rustpython"
version = "0.0.1"
authors = ["Windel Bouwman", "Shing Lyu <shing.lyu@gmail.com>"]
version = "0.1.0"
authors = ["RustPython Team"]
edition = "2018"
description = "A python interpreter written in rust."
repository = "https://github.com/RustPython/RustPython"
license = "MIT"
[workspace]
members = [".", "derive", "vm", "wasm/lib", "parser", "compiler", "bytecode"]
[[bench]]
name = "bench"
path = "./benchmarks/bench.rs"
[dependencies]
log="0.4.1"
env_logger="0.5.10"
clap = "2.31.2"
rustpython_parser = {path = "parser"}
rustpython_vm = {path = "vm"}
rustyline = "2.1.0"
rustpython-compiler = {path = "compiler", version = "0.1.0"}
rustpython-parser = {path = "parser", version = "0.1.0"}
rustpython-vm = {path = "vm", version = "0.1.0"}
rustyline = "4.1.0"
xdg = "2.2.0"
[dev-dependencies.cpython]
version = "0.2"

9
Dockerfile.bin Normal file
View File

@@ -0,0 +1,9 @@
FROM rust:1.31-slim
WORKDIR /rustpython
COPY . .
RUN cargo build --release
CMD [ "/rustpython/target/release/rustpython" ]

19
Dockerfile.wasm Normal file
View File

@@ -0,0 +1,19 @@
FROM rust:1.31-slim
RUN apt-get update && apt-get install curl gnupg -y && \
curl -o- https://deb.nodesource.com/setup_10.x | bash && \
apt-get install nodejs -y && \
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh && \
npm i -g serve
WORKDIR /rustpython
COPY . .
RUN cd ./wasm/lib/ && \
cargo build --release && \
cd ../demo && \
npm install && \
npm run dist
CMD [ "serve", "/rustpython/wasm/demo/dist" ]

254
Lib/PSF-LICENSE Normal file
View File

@@ -0,0 +1,254 @@
A. HISTORY OF THE SOFTWARE
==========================
Python was created in the early 1990s by Guido van Rossum at Stichting
Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
as a successor of a language called ABC. Guido remains Python's
principal author, although it includes many contributions from others.
In 1995, Guido continued his work on Python at the Corporation for
National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
in Reston, Virginia where he released several versions of the
software.
In May 2000, Guido and the Python core development team moved to
BeOpen.com to form the BeOpen PythonLabs team. In October of the same
year, the PythonLabs team moved to Digital Creations, which became
Zope Corporation. In 2001, the Python Software Foundation (PSF, see
https://www.python.org/psf/) was formed, a non-profit organization
created specifically to own Python-related Intellectual Property.
Zope Corporation was a sponsoring member of the PSF.
All Python releases are Open Source (see http://www.opensource.org for
the Open Source Definition). Historically, most, but not all, Python
releases have also been GPL-compatible; the table below summarizes
the various releases.
Release Derived Year Owner GPL-
from compatible? (1)
0.9.0 thru 1.2 1991-1995 CWI yes
1.3 thru 1.5.2 1.2 1995-1999 CNRI yes
1.6 1.5.2 2000 CNRI no
2.0 1.6 2000 BeOpen.com no
1.6.1 1.6 2001 CNRI yes (2)
2.1 2.0+1.6.1 2001 PSF no
2.0.1 2.0+1.6.1 2001 PSF yes
2.1.1 2.1+2.0.1 2001 PSF yes
2.1.2 2.1.1 2002 PSF yes
2.1.3 2.1.2 2002 PSF yes
2.2 and above 2.1.1 2001-now PSF yes
Footnotes:
(1) GPL-compatible doesn't mean that we're distributing Python under
the GPL. All Python licenses, unlike the GPL, let you distribute
a modified version without making your changes open source. The
GPL-compatible licenses make it possible to combine Python with
other software that is released under the GPL; the others don't.
(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
because its license has a choice of law clause. According to
CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
is "not incompatible" with the GPL.
Thanks to the many outside volunteers who have worked under Guido's
direction to make these releases possible.
B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
===============================================================
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
--------------------------------------------
1. This LICENSE AGREEMENT is between the Python Software Foundation
("PSF"), and the Individual or Organization ("Licensee") accessing and
otherwise using this software ("Python") in source or binary form and
its associated documentation.
2. Subject to the terms and conditions of this License Agreement, PSF hereby
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
analyze, test, perform and/or display publicly, prepare derivative works,
distribute, and otherwise use Python alone or in any derivative version,
provided, however, that PSF's License Agreement and PSF's notice of copyright,
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 Python Software Foundation; All
Rights Reserved" are retained in Python alone or in any derivative version
prepared by Licensee.
3. In the event Licensee prepares a derivative work that is based on
or incorporates Python or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python.
4. PSF is making Python available to Licensee on an "AS IS"
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
7. Nothing in this License Agreement shall be deemed to create any
relationship of agency, partnership, or joint venture between PSF and
Licensee. This License Agreement does not grant permission to use PSF
trademarks or trade name in a trademark sense to endorse or promote
products or services of Licensee, or any third party.
8. By copying, installing or otherwise using Python, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.
BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
-------------------------------------------
BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
Individual or Organization ("Licensee") accessing and otherwise using
this software in source or binary form and its associated
documentation ("the Software").
2. Subject to the terms and conditions of this BeOpen Python License
Agreement, BeOpen hereby grants Licensee a non-exclusive,
royalty-free, world-wide license to reproduce, analyze, test, perform
and/or display publicly, prepare derivative works, distribute, and
otherwise use the Software alone or in any derivative version,
provided, however, that the BeOpen Python License is retained in the
Software, alone or in any derivative version prepared by Licensee.
3. BeOpen is making the Software available to Licensee on an "AS IS"
basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
5. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
6. This License Agreement shall be governed by and interpreted in all
respects by the law of the State of California, excluding conflict of
law provisions. Nothing in this License Agreement shall be deemed to
create any relationship of agency, partnership, or joint venture
between BeOpen and Licensee. This License Agreement does not grant
permission to use BeOpen trademarks or trade names in a trademark
sense to endorse or promote products or services of Licensee, or any
third party. As an exception, the "BeOpen Python" logos available at
http://www.pythonlabs.com/logos.html may be used according to the
permissions granted on that web page.
7. By copying, installing or otherwise using the software, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.
CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
---------------------------------------
1. This LICENSE AGREEMENT is between the Corporation for National
Research Initiatives, having an office at 1895 Preston White Drive,
Reston, VA 20191 ("CNRI"), and the Individual or Organization
("Licensee") accessing and otherwise using Python 1.6.1 software in
source or binary form and its associated documentation.
2. Subject to the terms and conditions of this License Agreement, CNRI
hereby grants Licensee a nonexclusive, royalty-free, world-wide
license to reproduce, analyze, test, perform and/or display publicly,
prepare derivative works, distribute, and otherwise use Python 1.6.1
alone or in any derivative version, provided, however, that CNRI's
License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
1995-2001 Corporation for National Research Initiatives; All Rights
Reserved" are retained in Python 1.6.1 alone or in any derivative
version prepared by Licensee. Alternately, in lieu of CNRI's License
Agreement, Licensee may substitute the following text (omitting the
quotes): "Python 1.6.1 is made available subject to the terms and
conditions in CNRI's License Agreement. This Agreement together with
Python 1.6.1 may be located on the Internet using the following
unique, persistent identifier (known as a handle): 1895.22/1013. This
Agreement may also be obtained from a proxy server on the Internet
using the following URL: http://hdl.handle.net/1895.22/1013".
3. In the event Licensee prepares a derivative work that is based on
or incorporates Python 1.6.1 or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python 1.6.1.
4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
7. This License Agreement shall be governed by the federal
intellectual property law of the United States, including without
limitation the federal copyright law, and, to the extent such
U.S. federal law does not apply, by the law of the Commonwealth of
Virginia, excluding Virginia's conflict of law provisions.
Notwithstanding the foregoing, with regard to derivative works based
on Python 1.6.1 that incorporate non-separable material that was
previously distributed under the GNU General Public License (GPL), the
law of the Commonwealth of Virginia shall govern this License
Agreement only as to issues arising under or with respect to
Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
License Agreement shall be deemed to create any relationship of
agency, partnership, or joint venture between CNRI and Licensee. This
License Agreement does not grant permission to use CNRI trademarks or
trade name in a trademark sense to endorse or promote products or
services of Licensee, or any third party.
8. By clicking on the "ACCEPT" button where indicated, or by copying,
installing or otherwise using Python 1.6.1, Licensee agrees to be
bound by the terms and conditions of this License Agreement.
ACCEPT
CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
--------------------------------------------------
Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
The Netherlands. All rights reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

10
Lib/README.md Normal file
View File

@@ -0,0 +1,10 @@
Standard Library for RustPython
===============================
This directory contains all of the Python files that make up the standard library for RustPython.
Most of these files are copied over from the CPython repository(the 3.7 branch), with slight modifications to allow them
to work under RustPython. The current goal is to complete the standard library with as few modifications as possible.
Current modifications are just temporary workarounds for bugs/missing feature within the RustPython implementation.
The first target is to run the ``unittest`` module, so we can leverage the CPython test suite.

1013
Lib/_collections_abc.py Normal file

File diff suppressed because it is too large Load Diff

147
Lib/_py_abc.py Normal file
View File

@@ -0,0 +1,147 @@
from _weakrefset import WeakSet
def get_cache_token():
"""Returns the current ABC cache token.
The token is an opaque object (supporting equality testing) identifying the
current version of the ABC cache for virtual subclasses. The token changes
with every call to ``register()`` on any ABC.
"""
return ABCMeta._abc_invalidation_counter
class ABCMeta(type):
"""Metaclass for defining Abstract Base Classes (ABCs).
Use this metaclass to create an ABC. An ABC can be subclassed
directly, and then acts as a mix-in class. You can also register
unrelated concrete classes (even built-in classes) and unrelated
ABCs as 'virtual subclasses' -- these and their descendants will
be considered subclasses of the registering ABC by the built-in
issubclass() function, but the registering ABC won't show up in
their MRO (Method Resolution Order) nor will method
implementations defined by the registering ABC be callable (not
even via super()).
"""
# A global counter that is incremented each time a class is
# registered as a virtual subclass of anything. It forces the
# negative cache to be cleared before its next use.
# Note: this counter is private. Use `abc.get_cache_token()` for
# external code.
_abc_invalidation_counter = 0
def __new__(mcls, name, bases, namespace, **kwargs):
cls = type.__new__(mcls, name, bases, namespace, **kwargs)
# Compute set of abstract method names
abstracts = {name
for name, value in namespace.items()
if getattr(value, "__isabstractmethod__", False)}
for base in bases:
for name in getattr(base, "__abstractmethods__", set()):
value = getattr(cls, name, None)
if getattr(value, "__isabstractmethod__", False):
abstracts.add(name)
cls.__abstractmethods__ = set(abstracts)
# Set up inheritance registry
cls._abc_registry = WeakSet()
cls._abc_cache = WeakSet()
cls._abc_negative_cache = WeakSet()
cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
return cls
def register(cls, subclass):
"""Register a virtual subclass of an ABC.
Returns the subclass, to allow usage as a class decorator.
"""
if not isinstance(subclass, type):
raise TypeError("Can only register classes")
if issubclass(subclass, cls):
return subclass # Already a subclass
# Subtle: test for cycles *after* testing for "already a subclass";
# this means we allow X.register(X) and interpret it as a no-op.
if issubclass(cls, subclass):
# This would create a cycle, which is bad for the algorithm below
raise RuntimeError("Refusing to create an inheritance cycle")
cls._abc_registry.add(subclass)
ABCMeta._abc_invalidation_counter += 1 # Invalidate negative cache
return subclass
def _dump_registry(cls, file=None):
"""Debug helper to print the ABC registry."""
print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file)
print(f"Inv. counter: {get_cache_token()}", file=file)
for name in cls.__dict__:
if name.startswith("_abc_"):
value = getattr(cls, name)
if isinstance(value, WeakSet):
value = set(value)
print(f"{name}: {value!r}", file=file)
def _abc_registry_clear(cls):
"""Clear the registry (for debugging or testing)."""
cls._abc_registry.clear()
def _abc_caches_clear(cls):
"""Clear the caches (for debugging or testing)."""
cls._abc_cache.clear()
cls._abc_negative_cache.clear()
def __instancecheck__(cls, instance):
"""Override for isinstance(instance, cls)."""
# Inline the cache checking
subclass = instance.__class__
if subclass in cls._abc_cache:
return True
subtype = type(instance)
if subtype is subclass:
if (cls._abc_negative_cache_version ==
ABCMeta._abc_invalidation_counter and
subclass in cls._abc_negative_cache):
return False
# Fall back to the subclass check.
return cls.__subclasscheck__(subclass)
return any(cls.__subclasscheck__(c) for c in (subclass, subtype))
def __subclasscheck__(cls, subclass):
"""Override for issubclass(subclass, cls)."""
if not isinstance(subclass, type):
raise TypeError('issubclass() arg 1 must be a class')
# Check cache
if subclass in cls._abc_cache:
return True
# Check negative cache; may have to invalidate
if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter:
# Invalidate the negative cache
cls._abc_negative_cache = WeakSet()
cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
elif subclass in cls._abc_negative_cache:
return False
# Check the subclass hook
ok = cls.__subclasshook__(subclass)
if ok is not NotImplemented:
assert isinstance(ok, bool)
if ok:
cls._abc_cache.add(subclass)
else:
cls._abc_negative_cache.add(subclass)
return ok
# Check if it's a direct subclass
if cls in getattr(subclass, '__mro__', ()):
cls._abc_cache.add(subclass)
return True
# Check if it's a subclass of a registered class (recursive)
for rcls in cls._abc_registry:
if issubclass(subclass, rcls):
cls._abc_cache.add(subclass)
return True
# Check if it's a subclass of a subclass (recursive)
for scls in cls.__subclasses__():
if issubclass(subclass, scls):
cls._abc_cache.add(subclass)
return True
# No dice; update negative cache
cls._abc_negative_cache.add(subclass)
return False

196
Lib/_weakrefset.py Normal file
View File

@@ -0,0 +1,196 @@
# Access WeakSet through the weakref module.
# This code is separated-out because it is needed
# by abc.py to load everything else at startup.
from _weakref import ref
__all__ = ['WeakSet']
class _IterationGuard:
# This context manager registers itself in the current iterators of the
# weak container, such as to delay all removals until the context manager
# exits.
# This technique should be relatively thread-safe (since sets are).
def __init__(self, weakcontainer):
# Don't create cycles
self.weakcontainer = ref(weakcontainer)
def __enter__(self):
w = self.weakcontainer()
if w is not None:
w._iterating.add(self)
return self
def __exit__(self, e, t, b):
w = self.weakcontainer()
if w is not None:
s = w._iterating
s.remove(self)
if not s:
w._commit_removals()
class WeakSet:
def __init__(self, data=None):
self.data = set()
def _remove(item, selfref=ref(self)):
self = selfref()
if self is not None:
if self._iterating:
self._pending_removals.append(item)
else:
self.data.discard(item)
self._remove = _remove
# A list of keys to be removed
self._pending_removals = []
self._iterating = set()
if data is not None:
self.update(data)
def _commit_removals(self):
l = self._pending_removals
discard = self.data.discard
while l:
discard(l.pop())
def __iter__(self):
with _IterationGuard(self):
for itemref in self.data:
item = itemref()
if item is not None:
# Caveat: the iterator will keep a strong reference to
# `item` until it is resumed or closed.
yield item
def __len__(self):
return len(self.data) - len(self._pending_removals)
def __contains__(self, item):
try:
wr = ref(item)
except TypeError:
return False
return wr in self.data
def __reduce__(self):
return (self.__class__, (list(self),),
getattr(self, '__dict__', None))
def add(self, item):
if self._pending_removals:
self._commit_removals()
self.data.add(ref(item, self._remove))
def clear(self):
if self._pending_removals:
self._commit_removals()
self.data.clear()
def copy(self):
return self.__class__(self)
def pop(self):
if self._pending_removals:
self._commit_removals()
while True:
try:
itemref = self.data.pop()
except KeyError:
raise KeyError('pop from empty WeakSet') from None
item = itemref()
if item is not None:
return item
def remove(self, item):
if self._pending_removals:
self._commit_removals()
self.data.remove(ref(item))
def discard(self, item):
if self._pending_removals:
self._commit_removals()
self.data.discard(ref(item))
def update(self, other):
if self._pending_removals:
self._commit_removals()
for element in other:
self.add(element)
def __ior__(self, other):
self.update(other)
return self
def difference(self, other):
newset = self.copy()
newset.difference_update(other)
return newset
__sub__ = difference
def difference_update(self, other):
self.__isub__(other)
def __isub__(self, other):
if self._pending_removals:
self._commit_removals()
if self is other:
self.data.clear()
else:
self.data.difference_update(ref(item) for item in other)
return self
def intersection(self, other):
return self.__class__(item for item in other if item in self)
__and__ = intersection
def intersection_update(self, other):
self.__iand__(other)
def __iand__(self, other):
if self._pending_removals:
self._commit_removals()
self.data.intersection_update(ref(item) for item in other)
return self
def issubset(self, other):
return self.data.issubset(ref(item) for item in other)
__le__ = issubset
def __lt__(self, other):
return self.data < set(map(ref, other))
def issuperset(self, other):
return self.data.issuperset(ref(item) for item in other)
__ge__ = issuperset
def __gt__(self, other):
return self.data > set(map(ref, other))
def __eq__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
return self.data == set(map(ref, other))
def symmetric_difference(self, other):
newset = self.copy()
newset.symmetric_difference_update(other)
return newset
__xor__ = symmetric_difference
def symmetric_difference_update(self, other):
self.__ixor__(other)
def __ixor__(self, other):
if self._pending_removals:
self._commit_removals()
if self is other:
self.data.clear()
else:
self.data.symmetric_difference_update(ref(item, self._remove) for item in other)
return self
def union(self, other):
return self.__class__(e for s in (self, other) for e in s)
__or__ = union
def isdisjoint(self, other):
return len(self.intersection(other)) == 0

170
Lib/abc.py Normal file
View File

@@ -0,0 +1,170 @@
# Copyright 2007 Google, Inc. All Rights Reserved.
# Licensed to PSF under a Contributor Agreement.
"""Abstract Base Classes (ABCs) according to PEP 3119."""
def abstractmethod(funcobj):
"""A decorator indicating abstract methods.
Requires that the metaclass is ABCMeta or derived from it. A
class that has a metaclass derived from ABCMeta cannot be
instantiated unless all of its abstract methods are overridden.
The abstract methods can be called using any of the normal
'super' call mechanisms.
Usage:
class C(metaclass=ABCMeta):
@abstractmethod
def my_abstract_method(self, ...):
...
"""
funcobj.__isabstractmethod__ = True
return funcobj
class abstractclassmethod(classmethod):
"""A decorator indicating abstract classmethods.
Similar to abstractmethod.
Usage:
class C(metaclass=ABCMeta):
@abstractclassmethod
def my_abstract_classmethod(cls, ...):
...
'abstractclassmethod' is deprecated. Use 'classmethod' with
'abstractmethod' instead.
"""
__isabstractmethod__ = True
def __init__(self, callable):
callable.__isabstractmethod__ = True
super().__init__(callable)
class abstractstaticmethod(staticmethod):
"""A decorator indicating abstract staticmethods.
Similar to abstractmethod.
Usage:
class C(metaclass=ABCMeta):
@abstractstaticmethod
def my_abstract_staticmethod(...):
...
'abstractstaticmethod' is deprecated. Use 'staticmethod' with
'abstractmethod' instead.
"""
__isabstractmethod__ = True
def __init__(self, callable):
callable.__isabstractmethod__ = True
super().__init__(callable)
class abstractproperty(property):
"""A decorator indicating abstract properties.
Requires that the metaclass is ABCMeta or derived from it. A
class that has a metaclass derived from ABCMeta cannot be
instantiated unless all of its abstract properties are overridden.
The abstract properties can be called using any of the normal
'super' call mechanisms.
Usage:
class C(metaclass=ABCMeta):
@abstractproperty
def my_abstract_property(self):
...
This defines a read-only property; you can also define a read-write
abstract property using the 'long' form of property declaration:
class C(metaclass=ABCMeta):
def getx(self): ...
def setx(self, value): ...
x = abstractproperty(getx, setx)
'abstractproperty' is deprecated. Use 'property' with 'abstractmethod'
instead.
"""
__isabstractmethod__ = True
try:
from _abc import (get_cache_token, _abc_init, _abc_register,
_abc_instancecheck, _abc_subclasscheck, _get_dump,
_reset_registry, _reset_caches)
except ImportError:
from _py_abc import ABCMeta, get_cache_token
ABCMeta.__module__ = 'abc'
else:
class ABCMeta(type):
"""Metaclass for defining Abstract Base Classes (ABCs).
Use this metaclass to create an ABC. An ABC can be subclassed
directly, and then acts as a mix-in class. You can also register
unrelated concrete classes (even built-in classes) and unrelated
ABCs as 'virtual subclasses' -- these and their descendants will
be considered subclasses of the registering ABC by the built-in
issubclass() function, but the registering ABC won't show up in
their MRO (Method Resolution Order) nor will method
implementations defined by the registering ABC be callable (not
even via super()).
"""
def __new__(mcls, name, bases, namespace, **kwargs):
cls = super().__new__(mcls, name, bases, namespace, **kwargs)
_abc_init(cls)
return cls
def register(cls, subclass):
"""Register a virtual subclass of an ABC.
Returns the subclass, to allow usage as a class decorator.
"""
return _abc_register(cls, subclass)
def __instancecheck__(cls, instance):
"""Override for isinstance(instance, cls)."""
return _abc_instancecheck(cls, instance)
def __subclasscheck__(cls, subclass):
"""Override for issubclass(subclass, cls)."""
return _abc_subclasscheck(cls, subclass)
def _dump_registry(cls, file=None):
"""Debug helper to print the ABC registry."""
print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file)
print(f"Inv. counter: {get_cache_token()}", file=file)
(_abc_registry, _abc_cache, _abc_negative_cache,
_abc_negative_cache_version) = _get_dump(cls)
print(f"_abc_registry: {_abc_registry!r}", file=file)
print(f"_abc_cache: {_abc_cache!r}", file=file)
print(f"_abc_negative_cache: {_abc_negative_cache!r}", file=file)
print(f"_abc_negative_cache_version: {_abc_negative_cache_version!r}",
file=file)
def _abc_registry_clear(cls):
"""Clear the registry (for debugging or testing)."""
_reset_registry(cls)
def _abc_caches_clear(cls):
"""Clear the caches (for debugging or testing)."""
_reset_caches(cls)
class ABC(metaclass=ABCMeta):
"""Helper class that provides a standard way to create an ABC using
inheritance.
"""
__slots__ = ()

1279
Lib/collections/__init__.py Normal file

File diff suppressed because it is too large Load Diff

2
Lib/collections/abc.py Normal file
View File

@@ -0,0 +1,2 @@
from _collections_abc import *
from _collections_abc import __all__

2097
Lib/difflib.py Normal file

File diff suppressed because it is too large Load Diff

828
Lib/functools.py Normal file
View File

@@ -0,0 +1,828 @@
"""functools.py - Tools for working with functions and callable objects
"""
# Python module wrapper for _functools C module
# to allow utilities written in Python to be added
# to the functools module.
# Written by Nick Coghlan <ncoghlan at gmail.com>,
# Raymond Hettinger <python at rcn.com>,
# and Łukasz Langa <lukasz at langa.pl>.
# Copyright (C) 2006-2013 Python Software Foundation.
# See C source code for _functools credits/copyright
__all__ = ['update_wrapper', 'wraps', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES',
'total_ordering', 'cmp_to_key', 'lru_cache', 'reduce', 'partial',
'partialmethod', 'singledispatch']
try:
from _functools import reduce
except ImportError:
pass
from abc import get_cache_token
from collections import namedtuple
# import types, weakref # Deferred to single_dispatch()
from reprlib import recursive_repr
from _thread import RLock
################################################################################
### update_wrapper() and wraps() decorator
################################################################################
# update_wrapper() and wraps() are tools to help write
# wrapper functions that can handle naive introspection
WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__',
'__annotations__')
WRAPPER_UPDATES = ('__dict__',)
def update_wrapper(wrapper,
wrapped,
assigned = WRAPPER_ASSIGNMENTS,
updated = WRAPPER_UPDATES):
"""Update a wrapper function to look like the wrapped function
wrapper is the function to be updated
wrapped is the original function
assigned is a tuple naming the attributes assigned directly
from the wrapped function to the wrapper function (defaults to
functools.WRAPPER_ASSIGNMENTS)
updated is a tuple naming the attributes of the wrapper that
are updated with the corresponding attribute from the wrapped
function (defaults to functools.WRAPPER_UPDATES)
"""
for attr in assigned:
try:
value = getattr(wrapped, attr)
except AttributeError:
pass
else:
setattr(wrapper, attr, value)
for attr in updated:
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
# Issue #17482: set __wrapped__ last so we don't inadvertently copy it
# from the wrapped function when updating __dict__
wrapper.__wrapped__ = wrapped
# Return the wrapper so this can be used as a decorator via partial()
return wrapper
def wraps(wrapped,
assigned = WRAPPER_ASSIGNMENTS,
updated = WRAPPER_UPDATES):
"""Decorator factory to apply update_wrapper() to a wrapper function
Returns a decorator that invokes update_wrapper() with the decorated
function as the wrapper argument and the arguments to wraps() as the
remaining arguments. Default arguments are as for update_wrapper().
This is a convenience function to simplify applying partial() to
update_wrapper().
"""
return partial(update_wrapper, wrapped=wrapped,
assigned=assigned, updated=updated)
################################################################################
### total_ordering class decorator
################################################################################
# The total ordering functions all invoke the root magic method directly
# rather than using the corresponding operator. This avoids possible
# infinite recursion that could occur when the operator dispatch logic
# detects a NotImplemented result and then calls a reflected method.
def _gt_from_lt(self, other, NotImplemented=NotImplemented):
'Return a > b. Computed by @total_ordering from (not a < b) and (a != b).'
op_result = self.__lt__(other)
if op_result is NotImplemented:
return op_result
return not op_result and self != other
def _le_from_lt(self, other, NotImplemented=NotImplemented):
'Return a <= b. Computed by @total_ordering from (a < b) or (a == b).'
op_result = self.__lt__(other)
return op_result or self == other
def _ge_from_lt(self, other, NotImplemented=NotImplemented):
'Return a >= b. Computed by @total_ordering from (not a < b).'
op_result = self.__lt__(other)
if op_result is NotImplemented:
return op_result
return not op_result
def _ge_from_le(self, other, NotImplemented=NotImplemented):
'Return a >= b. Computed by @total_ordering from (not a <= b) or (a == b).'
op_result = self.__le__(other)
if op_result is NotImplemented:
return op_result
return not op_result or self == other
def _lt_from_le(self, other, NotImplemented=NotImplemented):
'Return a < b. Computed by @total_ordering from (a <= b) and (a != b).'
op_result = self.__le__(other)
if op_result is NotImplemented:
return op_result
return op_result and self != other
def _gt_from_le(self, other, NotImplemented=NotImplemented):
'Return a > b. Computed by @total_ordering from (not a <= b).'
op_result = self.__le__(other)
if op_result is NotImplemented:
return op_result
return not op_result
def _lt_from_gt(self, other, NotImplemented=NotImplemented):
'Return a < b. Computed by @total_ordering from (not a > b) and (a != b).'
op_result = self.__gt__(other)
if op_result is NotImplemented:
return op_result
return not op_result and self != other
def _ge_from_gt(self, other, NotImplemented=NotImplemented):
'Return a >= b. Computed by @total_ordering from (a > b) or (a == b).'
op_result = self.__gt__(other)
return op_result or self == other
def _le_from_gt(self, other, NotImplemented=NotImplemented):
'Return a <= b. Computed by @total_ordering from (not a > b).'
op_result = self.__gt__(other)
if op_result is NotImplemented:
return op_result
return not op_result
def _le_from_ge(self, other, NotImplemented=NotImplemented):
'Return a <= b. Computed by @total_ordering from (not a >= b) or (a == b).'
op_result = self.__ge__(other)
if op_result is NotImplemented:
return op_result
return not op_result or self == other
def _gt_from_ge(self, other, NotImplemented=NotImplemented):
'Return a > b. Computed by @total_ordering from (a >= b) and (a != b).'
op_result = self.__ge__(other)
if op_result is NotImplemented:
return op_result
return op_result and self != other
def _lt_from_ge(self, other, NotImplemented=NotImplemented):
'Return a < b. Computed by @total_ordering from (not a >= b).'
op_result = self.__ge__(other)
if op_result is NotImplemented:
return op_result
return not op_result
_convert = {
'__lt__': [('__gt__', _gt_from_lt),
('__le__', _le_from_lt),
('__ge__', _ge_from_lt)],
'__le__': [('__ge__', _ge_from_le),
('__lt__', _lt_from_le),
('__gt__', _gt_from_le)],
'__gt__': [('__lt__', _lt_from_gt),
('__ge__', _ge_from_gt),
('__le__', _le_from_gt)],
'__ge__': [('__le__', _le_from_ge),
('__gt__', _gt_from_ge),
('__lt__', _lt_from_ge)]
}
def total_ordering(cls):
"""Class decorator that fills in missing ordering methods"""
# Find user-defined comparisons (not those inherited from object).
roots = {op for op in _convert if getattr(cls, op, None) is not getattr(object, op, None)}
if not roots:
raise ValueError('must define at least one ordering operation: < > <= >=')
root = max(roots) # prefer __lt__ to __le__ to __gt__ to __ge__
for opname, opfunc in _convert[root]:
if opname not in roots:
opfunc.__name__ = opname
setattr(cls, opname, opfunc)
return cls
################################################################################
### cmp_to_key() function converter
################################################################################
def cmp_to_key(mycmp):
"""Convert a cmp= function into a key= function"""
class K(object):
__slots__ = ['obj']
def __init__(self, obj):
self.obj = obj
def __lt__(self, other):
return mycmp(self.obj, other.obj) < 0
def __gt__(self, other):
return mycmp(self.obj, other.obj) > 0
def __eq__(self, other):
return mycmp(self.obj, other.obj) == 0
def __le__(self, other):
return mycmp(self.obj, other.obj) <= 0
def __ge__(self, other):
return mycmp(self.obj, other.obj) >= 0
__hash__ = None
return K
try:
from _functools import cmp_to_key
except ImportError:
pass
################################################################################
### partial() argument application
################################################################################
# Purely functional, no descriptor behaviour
class partial:
"""New function with partial application of the given arguments
and keywords.
"""
__slots__ = "func", "args", "keywords", "__dict__", "__weakref__"
def __new__(*args, **keywords):
if not args:
raise TypeError("descriptor '__new__' of partial needs an argument")
if len(args) < 2:
raise TypeError("type 'partial' takes at least one argument")
cls, func, *args = args
if not callable(func):
raise TypeError("the first argument must be callable")
args = tuple(args)
if hasattr(func, "func"):
args = func.args + args
tmpkw = func.keywords.copy()
tmpkw.update(keywords)
keywords = tmpkw
del tmpkw
func = func.func
self = super(partial, cls).__new__(cls)
self.func = func
self.args = args
self.keywords = keywords
return self
def __call__(*args, **keywords):
if not args:
raise TypeError("descriptor '__call__' of partial needs an argument")
self, *args = args
newkeywords = self.keywords.copy()
newkeywords.update(keywords)
return self.func(*self.args, *args, **newkeywords)
@recursive_repr()
def __repr__(self):
qualname = type(self).__qualname__
args = [repr(self.func)]
args.extend(repr(x) for x in self.args)
args.extend(f"{k}={v!r}" for (k, v) in self.keywords.items())
if type(self).__module__ == "functools":
return f"functools.{qualname}({', '.join(args)})"
return f"{qualname}({', '.join(args)})"
def __reduce__(self):
return type(self), (self.func,), (self.func, self.args,
self.keywords or None, self.__dict__ or None)
def __setstate__(self, state):
if not isinstance(state, tuple):
raise TypeError("argument to __setstate__ must be a tuple")
if len(state) != 4:
raise TypeError(f"expected 4 items in state, got {len(state)}")
func, args, kwds, namespace = state
if (not callable(func) or not isinstance(args, tuple) or
(kwds is not None and not isinstance(kwds, dict)) or
(namespace is not None and not isinstance(namespace, dict))):
raise TypeError("invalid partial state")
args = tuple(args) # just in case it's a subclass
if kwds is None:
kwds = {}
elif type(kwds) is not dict: # XXX does it need to be *exactly* dict?
kwds = dict(kwds)
if namespace is None:
namespace = {}
self.__dict__ = namespace
self.func = func
self.args = args
self.keywords = kwds
try:
from _functools import partial
except ImportError:
pass
# Descriptor version
class partialmethod(object):
"""Method descriptor with partial application of the given arguments
and keywords.
Supports wrapping existing descriptors and handles non-descriptor
callables as instance methods.
"""
def __init__(self, func, *args, **keywords):
if not callable(func) and not hasattr(func, "__get__"):
raise TypeError("{!r} is not callable or a descriptor"
.format(func))
# func could be a descriptor like classmethod which isn't callable,
# so we can't inherit from partial (it verifies func is callable)
if isinstance(func, partialmethod):
# flattening is mandatory in order to place cls/self before all
# other arguments
# it's also more efficient since only one function will be called
self.func = func.func
self.args = func.args + args
self.keywords = func.keywords.copy()
self.keywords.update(keywords)
else:
self.func = func
self.args = args
self.keywords = keywords
def __repr__(self):
args = ", ".join(map(repr, self.args))
keywords = ", ".join("{}={!r}".format(k, v)
for k, v in self.keywords.items())
format_string = "{module}.{cls}({func}, {args}, {keywords})"
return format_string.format(module=self.__class__.__module__,
cls=self.__class__.__qualname__,
func=self.func,
args=args,
keywords=keywords)
def _make_unbound_method(self):
def _method(*args, **keywords):
call_keywords = self.keywords.copy()
call_keywords.update(keywords)
cls_or_self, *rest = args
call_args = (cls_or_self,) + self.args + tuple(rest)
return self.func(*call_args, **call_keywords)
_method.__isabstractmethod__ = self.__isabstractmethod__
_method._partialmethod = self
return _method
def __get__(self, obj, cls):
get = getattr(self.func, "__get__", None)
result = None
if get is not None:
new_func = get(obj, cls)
if new_func is not self.func:
# Assume __get__ returning something new indicates the
# creation of an appropriate callable
result = partial(new_func, *self.args, **self.keywords)
try:
result.__self__ = new_func.__self__
except AttributeError:
pass
if result is None:
# If the underlying descriptor didn't do anything, treat this
# like an instance method
result = self._make_unbound_method().__get__(obj, cls)
return result
@property
def __isabstractmethod__(self):
return getattr(self.func, "__isabstractmethod__", False)
################################################################################
### LRU Cache function decorator
################################################################################
_CacheInfo = namedtuple("CacheInfo", ["hits", "misses", "maxsize", "currsize"])
class _HashedSeq(list):
""" This class guarantees that hash() will be called no more than once
per element. This is important because the lru_cache() will hash
the key multiple times on a cache miss.
"""
__slots__ = 'hashvalue'
def __init__(self, tup, hash=hash):
self[:] = tup
self.hashvalue = hash(tup)
def __hash__(self):
return self.hashvalue
def _make_key(args, kwds, typed,
kwd_mark = (object(),),
fasttypes = {int, str, frozenset, type(None)},
tuple=tuple, type=type, len=len):
"""Make a cache key from optionally typed positional and keyword arguments
The key is constructed in a way that is flat as possible rather than
as a nested structure that would take more memory.
If there is only a single argument and its data type is known to cache
its hash value, then that argument is returned without a wrapper. This
saves space and improves lookup speed.
"""
# All of code below relies on kwds preserving the order input by the user.
# Formerly, we sorted() the kwds before looping. The new way is *much*
# faster; however, it means that f(x=1, y=2) will now be treated as a
# distinct call from f(y=2, x=1) which will be cached separately.
key = args
if kwds:
key += kwd_mark
for item in kwds.items():
key += item
if typed:
key += tuple(type(v) for v in args)
if kwds:
key += tuple(type(v) for v in kwds.values())
elif len(key) == 1 and type(key[0]) in fasttypes:
return key[0]
return _HashedSeq(key)
def lru_cache(maxsize=128, typed=False):
"""Least-recently-used cache decorator.
If *maxsize* is set to None, the LRU features are disabled and the cache
can grow without bound.
If *typed* is True, arguments of different types will be cached separately.
For example, f(3.0) and f(3) will be treated as distinct calls with
distinct results.
Arguments to the cached function must be hashable.
View the cache statistics named tuple (hits, misses, maxsize, currsize)
with f.cache_info(). Clear the cache and statistics with f.cache_clear().
Access the underlying function with f.__wrapped__.
See: http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used
"""
# Users should only access the lru_cache through its public API:
# cache_info, cache_clear, and f.__wrapped__
# The internals of the lru_cache are encapsulated for thread safety and
# to allow the implementation to change (including a possible C version).
# Early detection of an erroneous call to @lru_cache without any arguments
# resulting in the inner function being passed to maxsize instead of an
# integer or None.
if maxsize is not None and not isinstance(maxsize, int):
raise TypeError('Expected maxsize to be an integer or None')
def decorating_function(user_function):
wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
return update_wrapper(wrapper, user_function)
return decorating_function
def _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo):
# Constants shared by all lru cache instances:
sentinel = object() # unique object used to signal cache misses
make_key = _make_key # build a key from the function arguments
PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields
cache = {}
hits = misses = 0
full = False
cache_get = cache.get # bound method to lookup a key or return None
cache_len = cache.__len__ # get cache size without calling len()
lock = RLock() # because linkedlist updates aren't threadsafe
root = [] # root of the circular doubly linked list
root[:] = [root, root, None, None] # initialize by pointing to self
if maxsize == 0:
def wrapper(*args, **kwds):
# No caching -- just a statistics update after a successful call
nonlocal misses
result = user_function(*args, **kwds)
misses += 1
return result
elif maxsize is None:
def wrapper(*args, **kwds):
# Simple caching without ordering or size limit
nonlocal hits, misses
key = make_key(args, kwds, typed)
result = cache_get(key, sentinel)
if result is not sentinel:
hits += 1
return result
result = user_function(*args, **kwds)
cache[key] = result
misses += 1
return result
else:
def wrapper(*args, **kwds):
# Size limited caching that tracks accesses by recency
nonlocal root, hits, misses, full
key = make_key(args, kwds, typed)
with lock:
link = cache_get(key)
if link is not None:
# Move the link to the front of the circular queue
link_prev, link_next, _key, result = link
link_prev[NEXT] = link_next
link_next[PREV] = link_prev
last = root[PREV]
last[NEXT] = root[PREV] = link
link[PREV] = last
link[NEXT] = root
hits += 1
return result
result = user_function(*args, **kwds)
with lock:
if key in cache:
# Getting here means that this same key was added to the
# cache while the lock was released. Since the link
# update is already done, we need only return the
# computed result and update the count of misses.
pass
elif full:
# Use the old root to store the new key and result.
oldroot = root
oldroot[KEY] = key
oldroot[RESULT] = result
# Empty the oldest link and make it the new root.
# Keep a reference to the old key and old result to
# prevent their ref counts from going to zero during the
# update. That will prevent potentially arbitrary object
# clean-up code (i.e. __del__) from running while we're
# still adjusting the links.
root = oldroot[NEXT]
oldkey = root[KEY]
oldresult = root[RESULT]
root[KEY] = root[RESULT] = None
# Now update the cache dictionary.
del cache[oldkey]
# Save the potentially reentrant cache[key] assignment
# for last, after the root and links have been put in
# a consistent state.
cache[key] = oldroot
else:
# Put result in a new link at the front of the queue.
last = root[PREV]
link = [last, root, key, result]
last[NEXT] = root[PREV] = cache[key] = link
# Use the cache_len bound method instead of the len() function
# which could potentially be wrapped in an lru_cache itself.
full = (cache_len() >= maxsize)
misses += 1
return result
def cache_info():
"""Report cache statistics"""
with lock:
return _CacheInfo(hits, misses, maxsize, cache_len())
def cache_clear():
"""Clear the cache and cache statistics"""
nonlocal hits, misses, full
with lock:
cache.clear()
root[:] = [root, root, None, None]
hits = misses = 0
full = False
wrapper.cache_info = cache_info
wrapper.cache_clear = cache_clear
return wrapper
try:
from _functools import _lru_cache_wrapper
except ImportError:
pass
################################################################################
### singledispatch() - single-dispatch generic function decorator
################################################################################
def _c3_merge(sequences):
"""Merges MROs in *sequences* to a single MRO using the C3 algorithm.
Adapted from http://www.python.org/download/releases/2.3/mro/.
"""
result = []
while True:
sequences = [s for s in sequences if s] # purge empty sequences
if not sequences:
return result
for s1 in sequences: # find merge candidates among seq heads
candidate = s1[0]
for s2 in sequences:
if candidate in s2[1:]:
candidate = None
break # reject the current head, it appears later
else:
break
if candidate is None:
raise RuntimeError("Inconsistent hierarchy")
result.append(candidate)
# remove the chosen candidate
for seq in sequences:
if seq[0] == candidate:
del seq[0]
def _c3_mro(cls, abcs=None):
"""Computes the method resolution order using extended C3 linearization.
If no *abcs* are given, the algorithm works exactly like the built-in C3
linearization used for method resolution.
If given, *abcs* is a list of abstract base classes that should be inserted
into the resulting MRO. Unrelated ABCs are ignored and don't end up in the
result. The algorithm inserts ABCs where their functionality is introduced,
i.e. issubclass(cls, abc) returns True for the class itself but returns
False for all its direct base classes. Implicit ABCs for a given class
(either registered or inferred from the presence of a special method like
__len__) are inserted directly after the last ABC explicitly listed in the
MRO of said class. If two implicit ABCs end up next to each other in the
resulting MRO, their ordering depends on the order of types in *abcs*.
"""
for i, base in enumerate(reversed(cls.__bases__)):
if hasattr(base, '__abstractmethods__'):
boundary = len(cls.__bases__) - i
break # Bases up to the last explicit ABC are considered first.
else:
boundary = 0
abcs = list(abcs) if abcs else []
explicit_bases = list(cls.__bases__[:boundary])
abstract_bases = []
other_bases = list(cls.__bases__[boundary:])
for base in abcs:
if issubclass(cls, base) and not any(
issubclass(b, base) for b in cls.__bases__
):
# If *cls* is the class that introduces behaviour described by
# an ABC *base*, insert said ABC to its MRO.
abstract_bases.append(base)
for base in abstract_bases:
abcs.remove(base)
explicit_c3_mros = [_c3_mro(base, abcs=abcs) for base in explicit_bases]
abstract_c3_mros = [_c3_mro(base, abcs=abcs) for base in abstract_bases]
other_c3_mros = [_c3_mro(base, abcs=abcs) for base in other_bases]
return _c3_merge(
[[cls]] +
explicit_c3_mros + abstract_c3_mros + other_c3_mros +
[explicit_bases] + [abstract_bases] + [other_bases]
)
def _compose_mro(cls, types):
"""Calculates the method resolution order for a given class *cls*.
Includes relevant abstract base classes (with their respective bases) from
the *types* iterable. Uses a modified C3 linearization algorithm.
"""
bases = set(cls.__mro__)
# Remove entries which are already present in the __mro__ or unrelated.
def is_related(typ):
return (typ not in bases and hasattr(typ, '__mro__')
and issubclass(cls, typ))
types = [n for n in types if is_related(n)]
# Remove entries which are strict bases of other entries (they will end up
# in the MRO anyway.
def is_strict_base(typ):
for other in types:
if typ != other and typ in other.__mro__:
return True
return False
types = [n for n in types if not is_strict_base(n)]
# Subclasses of the ABCs in *types* which are also implemented by
# *cls* can be used to stabilize ABC ordering.
type_set = set(types)
mro = []
for typ in types:
found = []
for sub in typ.__subclasses__():
if sub not in bases and issubclass(cls, sub):
found.append([s for s in sub.__mro__ if s in type_set])
if not found:
mro.append(typ)
continue
# Favor subclasses with the biggest number of useful bases
found.sort(key=len, reverse=True)
for sub in found:
for subcls in sub:
if subcls not in mro:
mro.append(subcls)
return _c3_mro(cls, abcs=mro)
def _find_impl(cls, registry):
"""Returns the best matching implementation from *registry* for type *cls*.
Where there is no registered implementation for a specific type, its method
resolution order is used to find a more generic implementation.
Note: if *registry* does not contain an implementation for the base
*object* type, this function may return None.
"""
mro = _compose_mro(cls, registry.keys())
match = None
for t in mro:
if match is not None:
# If *match* is an implicit ABC but there is another unrelated,
# equally matching implicit ABC, refuse the temptation to guess.
if (t in registry and t not in cls.__mro__
and match not in cls.__mro__
and not issubclass(match, t)):
raise RuntimeError("Ambiguous dispatch: {} or {}".format(
match, t))
break
if t in registry:
match = t
return registry.get(match)
def singledispatch(func):
"""Single-dispatch generic function decorator.
Transforms a function into a generic function, which can have different
behaviours depending upon the type of its first argument. The decorated
function acts as the default implementation, and additional
implementations can be registered using the register() attribute of the
generic function.
"""
# There are many programs that use functools without singledispatch, so we
# trade-off making singledispatch marginally slower for the benefit of
# making start-up of such applications slightly faster.
import types, weakref
registry = {}
dispatch_cache = weakref.WeakKeyDictionary()
cache_token = None
def dispatch(cls):
"""generic_func.dispatch(cls) -> <function implementation>
Runs the dispatch algorithm to return the best available implementation
for the given *cls* registered on *generic_func*.
"""
nonlocal cache_token
if cache_token is not None:
current_token = get_cache_token()
if cache_token != current_token:
dispatch_cache.clear()
cache_token = current_token
try:
impl = dispatch_cache[cls]
except KeyError:
try:
impl = registry[cls]
except KeyError:
impl = _find_impl(cls, registry)
dispatch_cache[cls] = impl
return impl
def register(cls, func=None):
"""generic_func.register(cls, func) -> func
Registers a new implementation for the given *cls* on a *generic_func*.
"""
nonlocal cache_token
if func is None:
if isinstance(cls, type):
return lambda f: register(cls, f)
ann = getattr(cls, '__annotations__', {})
if not ann:
raise TypeError(
f"Invalid first argument to `register()`: {cls!r}. "
f"Use either `@register(some_class)` or plain `@register` "
f"on an annotated function."
)
func = cls
# only import typing if annotation parsing is necessary
from typing import get_type_hints
argname, cls = next(iter(get_type_hints(func).items()))
assert isinstance(cls, type), (
f"Invalid annotation for {argname!r}. {cls!r} is not a class."
)
registry[cls] = func
if cache_token is None and hasattr(cls, '__abstractmethods__'):
cache_token = get_cache_token()
dispatch_cache.clear()
return func
def wrapper(*args, **kw):
return dispatch(args[0].__class__)(*args, **kw)
registry[object] = func
wrapper.register = register
wrapper.dispatch = dispatch
wrapper.registry = types.MappingProxyType(registry)
wrapper._clear_cache = dispatch_cache.clear
update_wrapper(wrapper, func)
return wrapper

151
Lib/genericpath.py Normal file
View File

@@ -0,0 +1,151 @@
"""
Path operations common to more than one OS
Do not use directly. The OS specific modules import the appropriate
functions from this module themselves.
"""
import os
import stat
__all__ = ['commonprefix', 'exists', 'getatime', 'getctime', 'getmtime',
'getsize', 'isdir', 'isfile', 'samefile', 'sameopenfile',
'samestat']
# Does a path exist?
# This is false for dangling symbolic links on systems that support them.
def exists(path):
"""Test whether a path exists. Returns False for broken symbolic links"""
try:
os.stat(path)
except (OSError, ValueError):
return False
return True
# This follows symbolic links, so both islink() and isdir() can be true
# for the same path on systems that support symlinks
def isfile(path):
"""Test whether a path is a regular file"""
try:
st = os.stat(path)
except (OSError, ValueError):
return False
return stat.S_ISREG(st.st_mode)
# Is a path a directory?
# This follows symbolic links, so both islink() and isdir()
# can be true for the same path on systems that support symlinks
def isdir(s):
"""Return true if the pathname refers to an existing directory."""
try:
st = os.stat(s)
except (OSError, ValueError):
return False
return stat.S_ISDIR(st.st_mode)
def getsize(filename):
"""Return the size of a file, reported by os.stat()."""
return os.stat(filename).st_size
def getmtime(filename):
"""Return the last modification time of a file, reported by os.stat()."""
return os.stat(filename).st_mtime
def getatime(filename):
"""Return the last access time of a file, reported by os.stat()."""
return os.stat(filename).st_atime
def getctime(filename):
"""Return the metadata change time of a file, reported by os.stat()."""
return os.stat(filename).st_ctime
# Return the longest prefix of all list elements.
def commonprefix(m):
"Given a list of pathnames, returns the longest common leading component"
if not m: return ''
# Some people pass in a list of pathname parts to operate in an OS-agnostic
# fashion; don't try to translate in that case as that's an abuse of the
# API and they are already doing what they need to be OS-agnostic and so
# they most likely won't be using an os.PathLike object in the sublists.
if not isinstance(m[0], (list, tuple)):
m = tuple(map(os.fspath, m))
s1 = min(m)
s2 = max(m)
for i, c in enumerate(s1):
if c != s2[i]:
return s1[:i]
return s1
# Are two stat buffers (obtained from stat, fstat or lstat)
# describing the same file?
def samestat(s1, s2):
"""Test whether two stat buffers reference the same file"""
return (s1.st_ino == s2.st_ino and
s1.st_dev == s2.st_dev)
# Are two filenames really pointing to the same file?
def samefile(f1, f2):
"""Test whether two pathnames reference the same actual file"""
s1 = os.stat(f1)
s2 = os.stat(f2)
return samestat(s1, s2)
# Are two open files really referencing the same file?
# (Not necessarily the same file descriptor!)
def sameopenfile(fp1, fp2):
"""Test whether two open file objects reference the same file"""
s1 = os.fstat(fp1)
s2 = os.fstat(fp2)
return samestat(s1, s2)
# Split a path in root and extension.
# The extension is everything starting at the last dot in the last
# pathname component; the root is everything before that.
# It is always true that root + ext == p.
# Generic implementation of splitext, to be parametrized with
# the separators
def _splitext(p, sep, altsep, extsep):
"""Split the extension from a pathname.
Extension is everything from the last dot to the end, ignoring
leading dots. Returns "(root, ext)"; ext may be empty."""
# NOTE: This code must work for text and bytes strings.
sepIndex = p.rfind(sep)
if altsep:
altsepIndex = p.rfind(altsep)
sepIndex = max(sepIndex, altsepIndex)
dotIndex = p.rfind(extsep)
if dotIndex > sepIndex:
# skip all leading dots
filenameIndex = sepIndex + 1
while filenameIndex < dotIndex:
if p[filenameIndex:filenameIndex+1] != extsep:
return p[:dotIndex], p[dotIndex:]
filenameIndex += 1
return p, p[:0]
def _check_arg_types(funcname, *args):
hasstr = hasbytes = False
for s in args:
if isinstance(s, str):
hasstr = True
elif isinstance(s, bytes):
hasbytes = True
else:
raise TypeError('%s() argument must be str or bytes, not %r' %
(funcname, s.__class__.__name__)) from None
if hasstr and hasbytes:
raise TypeError("Can't mix strings and bytes in path components") from None

601
Lib/heapq.py Normal file
View File

@@ -0,0 +1,601 @@
"""Heap queue algorithm (a.k.a. priority queue).
Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for
all k, counting elements from 0. For the sake of comparison,
non-existing elements are considered to be infinite. The interesting
property of a heap is that a[0] is always its smallest element.
Usage:
heap = [] # creates an empty heap
heappush(heap, item) # pushes a new item on the heap
item = heappop(heap) # pops the smallest item from the heap
item = heap[0] # smallest item on the heap without popping it
heapify(x) # transforms list into a heap, in-place, in linear time
item = heapreplace(heap, item) # pops and returns smallest item, and adds
# new item; the heap size is unchanged
Our API differs from textbook heap algorithms as follows:
- We use 0-based indexing. This makes the relationship between the
index for a node and the indexes for its children slightly less
obvious, but is more suitable since Python uses 0-based indexing.
- Our heappop() method returns the smallest item, not the largest.
These two make it possible to view the heap as a regular Python list
without surprises: heap[0] is the smallest item, and heap.sort()
maintains the heap invariant!
"""
# Original code by Kevin O'Connor, augmented by Tim Peters and Raymond Hettinger
__about__ = """Heap queues
[explanation by François Pinard]
Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for
all k, counting elements from 0. For the sake of comparison,
non-existing elements are considered to be infinite. The interesting
property of a heap is that a[0] is always its smallest element.
The strange invariant above is meant to be an efficient memory
representation for a tournament. The numbers below are `k', not a[k]:
0
1 2
3 4 5 6
7 8 9 10 11 12 13 14
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
In the tree above, each cell `k' is topping `2*k+1' and `2*k+2'. In
a usual binary tournament we see in sports, each cell is the winner
over the two cells it tops, and we can trace the winner down the tree
to see all opponents s/he had. However, in many computer applications
of such tournaments, we do not need to trace the history of a winner.
To be more memory efficient, when a winner is promoted, we try to
replace it by something else at a lower level, and the rule becomes
that a cell and the two cells it tops contain three different items,
but the top cell "wins" over the two topped cells.
If this heap invariant is protected at all time, index 0 is clearly
the overall winner. The simplest algorithmic way to remove it and
find the "next" winner is to move some loser (let's say cell 30 in the
diagram above) into the 0 position, and then percolate this new 0 down
the tree, exchanging values, until the invariant is re-established.
This is clearly logarithmic on the total number of items in the tree.
By iterating over all items, you get an O(n ln n) sort.
A nice feature of this sort is that you can efficiently insert new
items while the sort is going on, provided that the inserted items are
not "better" than the last 0'th element you extracted. This is
especially useful in simulation contexts, where the tree holds all
incoming events, and the "win" condition means the smallest scheduled
time. When an event schedule other events for execution, they are
scheduled into the future, so they can easily go into the heap. So, a
heap is a good structure for implementing schedulers (this is what I
used for my MIDI sequencer :-).
Various structures for implementing schedulers have been extensively
studied, and heaps are good for this, as they are reasonably speedy,
the speed is almost constant, and the worst case is not much different
than the average case. However, there are other representations which
are more efficient overall, yet the worst cases might be terrible.
Heaps are also very useful in big disk sorts. You most probably all
know that a big sort implies producing "runs" (which are pre-sorted
sequences, which size is usually related to the amount of CPU memory),
followed by a merging passes for these runs, which merging is often
very cleverly organised[1]. It is very important that the initial
sort produces the longest runs possible. Tournaments are a good way
to that. If, using all the memory available to hold a tournament, you
replace and percolate items that happen to fit the current run, you'll
produce runs which are twice the size of the memory for random input,
and much better for input fuzzily ordered.
Moreover, if you output the 0'th item on disk and get an input which
may not fit in the current tournament (because the value "wins" over
the last output value), it cannot fit in the heap, so the size of the
heap decreases. The freed memory could be cleverly reused immediately
for progressively building a second heap, which grows at exactly the
same rate the first heap is melting. When the first heap completely
vanishes, you switch heaps and start a new run. Clever and quite
effective!
In a word, heaps are useful memory structures to know. I use them in
a few applications, and I think it is good to keep a `heap' module
around. :-)
--------------------
[1] The disk balancing algorithms which are current, nowadays, are
more annoying than clever, and this is a consequence of the seeking
capabilities of the disks. On devices which cannot seek, like big
tape drives, the story was quite different, and one had to be very
clever to ensure (far in advance) that each tape movement will be the
most effective possible (that is, will best participate at
"progressing" the merge). Some tapes were even able to read
backwards, and this was also used to avoid the rewinding time.
Believe me, real good tape sorts were quite spectacular to watch!
From all times, sorting has always been a Great Art! :-)
"""
__all__ = ['heappush', 'heappop', 'heapify', 'heapreplace', 'merge',
'nlargest', 'nsmallest', 'heappushpop']
def heappush(heap, item):
"""Push item onto heap, maintaining the heap invariant."""
heap.append(item)
_siftdown(heap, 0, len(heap)-1)
def heappop(heap):
"""Pop the smallest item off the heap, maintaining the heap invariant."""
lastelt = heap.pop() # raises appropriate IndexError if heap is empty
if heap:
returnitem = heap[0]
heap[0] = lastelt
_siftup(heap, 0)
return returnitem
return lastelt
def heapreplace(heap, item):
"""Pop and return the current smallest value, and add the new item.
This is more efficient than heappop() followed by heappush(), and can be
more appropriate when using a fixed-size heap. Note that the value
returned may be larger than item! That constrains reasonable uses of
this routine unless written as part of a conditional replacement:
if item > heap[0]:
item = heapreplace(heap, item)
"""
returnitem = heap[0] # raises appropriate IndexError if heap is empty
heap[0] = item
_siftup(heap, 0)
return returnitem
def heappushpop(heap, item):
"""Fast version of a heappush followed by a heappop."""
if heap and heap[0] < item:
item, heap[0] = heap[0], item
_siftup(heap, 0)
return item
def heapify(x):
"""Transform list into a heap, in-place, in O(len(x)) time."""
n = len(x)
# Transform bottom-up. The largest index there's any point to looking at
# is the largest with a child index in-range, so must have 2*i + 1 < n,
# or i < (n-1)/2. If n is even = 2*j, this is (2*j-1)/2 = j-1/2 so
# j-1 is the largest, which is n//2 - 1. If n is odd = 2*j+1, this is
# (2*j+1-1)/2 = j so j-1 is the largest, and that's again n//2-1.
for i in reversed(range(n//2)):
_siftup(x, i)
def _heappop_max(heap):
"""Maxheap version of a heappop."""
lastelt = heap.pop() # raises appropriate IndexError if heap is empty
if heap:
returnitem = heap[0]
heap[0] = lastelt
_siftup_max(heap, 0)
return returnitem
return lastelt
def _heapreplace_max(heap, item):
"""Maxheap version of a heappop followed by a heappush."""
returnitem = heap[0] # raises appropriate IndexError if heap is empty
heap[0] = item
_siftup_max(heap, 0)
return returnitem
def _heapify_max(x):
"""Transform list into a maxheap, in-place, in O(len(x)) time."""
n = len(x)
for i in reversed(range(n//2)):
_siftup_max(x, i)
# 'heap' is a heap at all indices >= startpos, except possibly for pos. pos
# is the index of a leaf with a possibly out-of-order value. Restore the
# heap invariant.
def _siftdown(heap, startpos, pos):
newitem = heap[pos]
# Follow the path to the root, moving parents down until finding a place
# newitem fits.
while pos > startpos:
parentpos = (pos - 1) >> 1
parent = heap[parentpos]
if newitem < parent:
heap[pos] = parent
pos = parentpos
continue
break
heap[pos] = newitem
# The child indices of heap index pos are already heaps, and we want to make
# a heap at index pos too. We do this by bubbling the smaller child of
# pos up (and so on with that child's children, etc) until hitting a leaf,
# then using _siftdown to move the oddball originally at index pos into place.
#
# We *could* break out of the loop as soon as we find a pos where newitem <=
# both its children, but turns out that's not a good idea, and despite that
# many books write the algorithm that way. During a heap pop, the last array
# element is sifted in, and that tends to be large, so that comparing it
# against values starting from the root usually doesn't pay (= usually doesn't
# get us out of the loop early). See Knuth, Volume 3, where this is
# explained and quantified in an exercise.
#
# Cutting the # of comparisons is important, since these routines have no
# way to extract "the priority" from an array element, so that intelligence
# is likely to be hiding in custom comparison methods, or in array elements
# storing (priority, record) tuples. Comparisons are thus potentially
# expensive.
#
# On random arrays of length 1000, making this change cut the number of
# comparisons made by heapify() a little, and those made by exhaustive
# heappop() a lot, in accord with theory. Here are typical results from 3
# runs (3 just to demonstrate how small the variance is):
#
# Compares needed by heapify Compares needed by 1000 heappops
# -------------------------- --------------------------------
# 1837 cut to 1663 14996 cut to 8680
# 1855 cut to 1659 14966 cut to 8678
# 1847 cut to 1660 15024 cut to 8703
#
# Building the heap by using heappush() 1000 times instead required
# 2198, 2148, and 2219 compares: heapify() is more efficient, when
# you can use it.
#
# The total compares needed by list.sort() on the same lists were 8627,
# 8627, and 8632 (this should be compared to the sum of heapify() and
# heappop() compares): list.sort() is (unsurprisingly!) more efficient
# for sorting.
def _siftup(heap, pos):
endpos = len(heap)
startpos = pos
newitem = heap[pos]
# Bubble up the smaller child until hitting a leaf.
childpos = 2*pos + 1 # leftmost child position
while childpos < endpos:
# Set childpos to index of smaller child.
rightpos = childpos + 1
if rightpos < endpos and not heap[childpos] < heap[rightpos]:
childpos = rightpos
# Move the smaller child up.
heap[pos] = heap[childpos]
pos = childpos
childpos = 2*pos + 1
# The leaf at pos is empty now. Put newitem there, and bubble it up
# to its final resting place (by sifting its parents down).
heap[pos] = newitem
_siftdown(heap, startpos, pos)
def _siftdown_max(heap, startpos, pos):
'Maxheap variant of _siftdown'
newitem = heap[pos]
# Follow the path to the root, moving parents down until finding a place
# newitem fits.
while pos > startpos:
parentpos = (pos - 1) >> 1
parent = heap[parentpos]
if parent < newitem:
heap[pos] = parent
pos = parentpos
continue
break
heap[pos] = newitem
def _siftup_max(heap, pos):
'Maxheap variant of _siftup'
endpos = len(heap)
startpos = pos
newitem = heap[pos]
# Bubble up the larger child until hitting a leaf.
childpos = 2*pos + 1 # leftmost child position
while childpos < endpos:
# Set childpos to index of larger child.
rightpos = childpos + 1
if rightpos < endpos and not heap[rightpos] < heap[childpos]:
childpos = rightpos
# Move the larger child up.
heap[pos] = heap[childpos]
pos = childpos
childpos = 2*pos + 1
# The leaf at pos is empty now. Put newitem there, and bubble it up
# to its final resting place (by sifting its parents down).
heap[pos] = newitem
_siftdown_max(heap, startpos, pos)
def merge(*iterables, key=None, reverse=False):
'''Merge multiple sorted inputs into a single sorted output.
Similar to sorted(itertools.chain(*iterables)) but returns a generator,
does not pull the data into memory all at once, and assumes that each of
the input streams is already sorted (smallest to largest).
>>> list(merge([1,3,5,7], [0,2,4,8], [5,10,15,20], [], [25]))
[0, 1, 2, 3, 4, 5, 5, 7, 8, 10, 15, 20, 25]
If *key* is not None, applies a key function to each element to determine
its sort order.
>>> list(merge(['dog', 'horse'], ['cat', 'fish', 'kangaroo'], key=len))
['dog', 'cat', 'fish', 'horse', 'kangaroo']
'''
h = []
h_append = h.append
if reverse:
_heapify = _heapify_max
_heappop = _heappop_max
_heapreplace = _heapreplace_max
direction = -1
else:
_heapify = heapify
_heappop = heappop
_heapreplace = heapreplace
direction = 1
if key is None:
for order, it in enumerate(map(iter, iterables)):
try:
next = it.__next__
h_append([next(), order * direction, next])
except StopIteration:
pass
_heapify(h)
while len(h) > 1:
try:
while True:
value, order, next = s = h[0]
yield value
s[0] = next() # raises StopIteration when exhausted
_heapreplace(h, s) # restore heap condition
except StopIteration:
_heappop(h) # remove empty iterator
if h:
# fast case when only a single iterator remains
value, order, next = h[0]
yield value
yield from next.__self__
return
for order, it in enumerate(map(iter, iterables)):
try:
next = it.__next__
value = next()
h_append([key(value), order * direction, value, next])
except StopIteration:
pass
_heapify(h)
while len(h) > 1:
try:
while True:
key_value, order, value, next = s = h[0]
yield value
value = next()
s[0] = key(value)
s[2] = value
_heapreplace(h, s)
except StopIteration:
_heappop(h)
if h:
key_value, order, value, next = h[0]
yield value
yield from next.__self__
# Algorithm notes for nlargest() and nsmallest()
# ==============================================
#
# Make a single pass over the data while keeping the k most extreme values
# in a heap. Memory consumption is limited to keeping k values in a list.
#
# Measured performance for random inputs:
#
# number of comparisons
# n inputs k-extreme values (average of 5 trials) % more than min()
# ------------- ---------------- --------------------- -----------------
# 1,000 100 3,317 231.7%
# 10,000 100 14,046 40.5%
# 100,000 100 105,749 5.7%
# 1,000,000 100 1,007,751 0.8%
# 10,000,000 100 10,009,401 0.1%
#
# Theoretical number of comparisons for k smallest of n random inputs:
#
# Step Comparisons Action
# ---- -------------------------- ---------------------------
# 1 1.66 * k heapify the first k-inputs
# 2 n - k compare remaining elements to top of heap
# 3 k * (1 + lg2(k)) * ln(n/k) replace the topmost value on the heap
# 4 k * lg2(k) - (k/2) final sort of the k most extreme values
#
# Combining and simplifying for a rough estimate gives:
#
# comparisons = n + k * (log(k, 2) * log(n/k) + log(k, 2) + log(n/k))
#
# Computing the number of comparisons for step 3:
# -----------------------------------------------
# * For the i-th new value from the iterable, the probability of being in the
# k most extreme values is k/i. For example, the probability of the 101st
# value seen being in the 100 most extreme values is 100/101.
# * If the value is a new extreme value, the cost of inserting it into the
# heap is 1 + log(k, 2).
# * The probability times the cost gives:
# (k/i) * (1 + log(k, 2))
# * Summing across the remaining n-k elements gives:
# sum((k/i) * (1 + log(k, 2)) for i in range(k+1, n+1))
# * This reduces to:
# (H(n) - H(k)) * k * (1 + log(k, 2))
# * Where H(n) is the n-th harmonic number estimated by:
# gamma = 0.5772156649
# H(n) = log(n, e) + gamma + 1 / (2 * n)
# http://en.wikipedia.org/wiki/Harmonic_series_(mathematics)#Rate_of_divergence
# * Substituting the H(n) formula:
# comparisons = k * (1 + log(k, 2)) * (log(n/k, e) + (1/n - 1/k) / 2)
#
# Worst-case for step 3:
# ----------------------
# In the worst case, the input data is reversed sorted so that every new element
# must be inserted in the heap:
#
# comparisons = 1.66 * k + log(k, 2) * (n - k)
#
# Alternative Algorithms
# ----------------------
# Other algorithms were not used because they:
# 1) Took much more auxiliary memory,
# 2) Made multiple passes over the data.
# 3) Made more comparisons in common cases (small k, large n, semi-random input).
# See the more detailed comparison of approach at:
# http://code.activestate.com/recipes/577573-compare-algorithms-for-heapqsmallest
def nsmallest(n, iterable, key=None):
"""Find the n smallest elements in a dataset.
Equivalent to: sorted(iterable, key=key)[:n]
"""
# Short-cut for n==1 is to use min()
if n == 1:
it = iter(iterable)
sentinel = object()
result = min(it, default=sentinel, key=key)
return [] if result is sentinel else [result]
# When n>=size, it's faster to use sorted()
try:
size = len(iterable)
except (TypeError, AttributeError):
pass
else:
if n >= size:
return sorted(iterable, key=key)[:n]
# When key is none, use simpler decoration
if key is None:
it = iter(iterable)
# put the range(n) first so that zip() doesn't
# consume one too many elements from the iterator
result = [(elem, i) for i, elem in zip(range(n), it)]
if not result:
return result
_heapify_max(result)
top = result[0][0]
order = n
_heapreplace = _heapreplace_max
for elem in it:
if elem < top:
_heapreplace(result, (elem, order))
top, _order = result[0]
order += 1
result.sort()
return [elem for (elem, order) in result]
# General case, slowest method
it = iter(iterable)
result = [(key(elem), i, elem) for i, elem in zip(range(n), it)]
if not result:
return result
_heapify_max(result)
top = result[0][0]
order = n
_heapreplace = _heapreplace_max
for elem in it:
k = key(elem)
if k < top:
_heapreplace(result, (k, order, elem))
top, _order, _elem = result[0]
order += 1
result.sort()
return [elem for (k, order, elem) in result]
def nlargest(n, iterable, key=None):
"""Find the n largest elements in a dataset.
Equivalent to: sorted(iterable, key=key, reverse=True)[:n]
"""
# Short-cut for n==1 is to use max()
if n == 1:
it = iter(iterable)
sentinel = object()
result = max(it, default=sentinel, key=key)
return [] if result is sentinel else [result]
# When n>=size, it's faster to use sorted()
try:
size = len(iterable)
except (TypeError, AttributeError):
pass
else:
if n >= size:
return sorted(iterable, key=key, reverse=True)[:n]
# When key is none, use simpler decoration
if key is None:
it = iter(iterable)
result = [(elem, i) for i, elem in zip(range(0, -n, -1), it)]
if not result:
return result
heapify(result)
top = result[0][0]
order = -n
_heapreplace = heapreplace
for elem in it:
if top < elem:
_heapreplace(result, (elem, order))
top, _order = result[0]
order -= 1
result.sort(reverse=True)
return [elem for (elem, order) in result]
# General case, slowest method
it = iter(iterable)
result = [(key(elem), i, elem) for i, elem in zip(range(0, -n, -1), it)]
if not result:
return result
heapify(result)
top = result[0][0]
order = -n
_heapreplace = heapreplace
for elem in it:
k = key(elem)
if top < k:
_heapreplace(result, (k, order, elem))
top, _order, _elem = result[0]
order -= 1
result.sort(reverse=True)
return [elem for (k, order, elem) in result]
# If available, use C implementation
try:
from _heapq import *
except ImportError:
pass
try:
from _heapq import _heapreplace_max
except ImportError:
pass
try:
from _heapq import _heapify_max
except ImportError:
pass
try:
from _heapq import _heappop_max
except ImportError:
pass
if __name__ == "__main__":
import doctest
print(doctest.testmod())

1173
Lib/importlib/_bootstrap.py Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1
Lib/io.py Normal file
View File

@@ -0,0 +1 @@
from _io import *

177
Lib/linecache.py Normal file
View File

@@ -0,0 +1,177 @@
"""Cache lines from Python source files.
This is intended to read lines from modules imported -- hence if a filename
is not found, it will look down the module search path for a file by
that name.
"""
import functools
import sys
import os
import tokenize
__all__ = ["getline", "clearcache", "checkcache"]
def getline(filename, lineno, module_globals=None):
lines = getlines(filename, module_globals)
if 1 <= lineno <= len(lines):
return lines[lineno-1]
else:
return ''
# The cache
# The cache. Maps filenames to either a thunk which will provide source code,
# or a tuple (size, mtime, lines, fullname) once loaded.
cache = {}
def clearcache():
"""Clear the cache entirely."""
global cache
cache = {}
def getlines(filename, module_globals=None):
"""Get the lines for a Python source file from the cache.
Update the cache if it doesn't contain an entry for this file already."""
if filename in cache:
entry = cache[filename]
if len(entry) != 1:
return cache[filename][2]
try:
return updatecache(filename, module_globals)
except MemoryError:
clearcache()
return []
def checkcache(filename=None):
"""Discard cache entries that are out of date.
(This is not checked upon each call!)"""
if filename is None:
filenames = list(cache.keys())
else:
if filename in cache:
filenames = [filename]
else:
return
for filename in filenames:
entry = cache[filename]
if len(entry) == 1:
# lazy cache entry, leave it lazy.
continue
size, mtime, lines, fullname = entry
if mtime is None:
continue # no-op for files loaded via a __loader__
try:
stat = os.stat(fullname)
except OSError:
del cache[filename]
continue
if size != stat.st_size or mtime != stat.st_mtime:
del cache[filename]
def updatecache(filename, module_globals=None):
"""Update a cache entry and return its list of lines.
If something's wrong, print a message, discard the cache entry,
and return an empty list."""
if filename in cache:
if len(cache[filename]) != 1:
del cache[filename]
if not filename or (filename.startswith('<') and filename.endswith('>')):
return []
fullname = filename
try:
stat = os.stat(fullname)
except OSError:
basename = filename
# Realise a lazy loader based lookup if there is one
# otherwise try to lookup right now.
if lazycache(filename, module_globals):
try:
data = cache[filename][0]()
except (ImportError, OSError):
pass
else:
if data is None:
# No luck, the PEP302 loader cannot find the source
# for this module.
return []
cache[filename] = (
len(data), None,
[line+'\n' for line in data.splitlines()], fullname
)
return cache[filename][2]
# Try looking through the module search path, which is only useful
# when handling a relative filename.
if os.path.isabs(filename):
return []
for dirname in sys.path:
try:
fullname = os.path.join(dirname, basename)
except (TypeError, AttributeError):
# Not sufficiently string-like to do anything useful with.
continue
try:
stat = os.stat(fullname)
break
except OSError:
pass
else:
return []
try:
with tokenize.open(fullname) as fp:
lines = fp.readlines()
except OSError:
return []
if lines and not lines[-1].endswith('\n'):
lines[-1] += '\n'
size, mtime = stat.st_size, stat.st_mtime
cache[filename] = size, mtime, lines, fullname
return lines
def lazycache(filename, module_globals):
"""Seed the cache for filename with module_globals.
The module loader will be asked for the source only when getlines is
called, not immediately.
If there is an entry in the cache already, it is not altered.
:return: True if a lazy load is registered in the cache,
otherwise False. To register such a load a module loader with a
get_source method must be found, the filename must be a cachable
filename, and the filename must not be already cached.
"""
if filename in cache:
if len(cache[filename]) == 1:
return True
else:
return False
if not filename or (filename.startswith('<') and filename.endswith('>')):
return False
# Try for a __loader__, if available
if module_globals and '__loader__' in module_globals:
name = module_globals.get('__name__')
loader = module_globals['__loader__']
get_source = getattr(loader, 'get_source', None)
if name and get_source:
get_lines = functools.partial(get_source, name)
cache[filename] = (get_lines,)
return True
return False

661
Lib/ntpath.py Normal file
View File

@@ -0,0 +1,661 @@
# Module 'ntpath' -- common operations on WinNT/Win95 pathnames
"""Common pathname manipulations, WindowsNT/95 version.
Instead of importing this module directly, import os and refer to this
module as os.path.
"""
# strings representing various path-related bits and pieces
# These are primarily for export; internally, they are hardcoded.
# Should be set before imports for resolving cyclic dependency.
curdir = '.'
pardir = '..'
extsep = '.'
sep = '\\'
pathsep = ';'
altsep = '/'
defpath = '.;C:\\bin'
devnull = 'nul'
import os
import sys
import stat
import genericpath
from genericpath import *
__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
"basename","dirname","commonprefix","getsize","getmtime",
"getatime","getctime", "islink","exists","lexists","isdir","isfile",
"ismount", "expanduser","expandvars","normpath","abspath",
"curdir","pardir","sep","pathsep","defpath","altsep",
"extsep","devnull","realpath","supports_unicode_filenames","relpath",
"samefile", "sameopenfile", "samestat", "commonpath"]
def _get_bothseps(path):
if isinstance(path, bytes):
return b'\\/'
else:
return '\\/'
# Normalize the case of a pathname and map slashes to backslashes.
# Other normalizations (such as optimizing '../' away) are not done
# (this is done by normpath).
def normcase(s):
"""Normalize case of pathname.
Makes all characters lowercase and all slashes into backslashes."""
s = os.fspath(s)
if isinstance(s, bytes):
return s.replace(b'/', b'\\').lower()
else:
return s.replace('/', '\\').lower()
# Return whether a path is absolute.
# Trivial in Posix, harder on Windows.
# For Windows it is absolute if it starts with a slash or backslash (current
# volume), or if a pathname after the volume-letter-and-colon or UNC-resource
# starts with a slash or backslash.
def isabs(s):
"""Test whether a path is absolute"""
s = os.fspath(s)
s = splitdrive(s)[1]
return len(s) > 0 and s[0] in _get_bothseps(s)
# Join two (or more) paths.
def join(path, *paths):
path = os.fspath(path)
if isinstance(path, bytes):
sep = b'\\'
seps = b'\\/'
colon = b':'
else:
sep = '\\'
seps = '\\/'
colon = ':'
try:
if not paths:
path[:0] + sep #23780: Ensure compatible data type even if p is null.
result_drive, result_path = splitdrive(path)
for p in map(os.fspath, paths):
p_drive, p_path = splitdrive(p)
if p_path and p_path[0] in seps:
# Second path is absolute
if p_drive or not result_drive:
result_drive = p_drive
result_path = p_path
continue
elif p_drive and p_drive != result_drive:
if p_drive.lower() != result_drive.lower():
# Different drives => ignore the first path entirely
result_drive = p_drive
result_path = p_path
continue
# Same drive in different case
result_drive = p_drive
# Second path is relative to the first
if result_path and result_path[-1] not in seps:
result_path = result_path + sep
result_path = result_path + p_path
## add separator between UNC and non-absolute path
if (result_path and result_path[0] not in seps and
result_drive and result_drive[-1:] != colon):
return result_drive + sep + result_path
return result_drive + result_path
except (TypeError, AttributeError, BytesWarning):
genericpath._check_arg_types('join', path, *paths)
raise
# Split a path in a drive specification (a drive letter followed by a
# colon) and the path specification.
# It is always true that drivespec + pathspec == p
def splitdrive(p):
"""Split a pathname into drive/UNC sharepoint and relative path specifiers.
Returns a 2-tuple (drive_or_unc, path); either part may be empty.
If you assign
result = splitdrive(p)
It is always true that:
result[0] + result[1] == p
If the path contained a drive letter, drive_or_unc will contain everything
up to and including the colon. e.g. splitdrive("c:/dir") returns ("c:", "/dir")
If the path contained a UNC path, the drive_or_unc will contain the host name
and share up to but not including the fourth directory separator character.
e.g. splitdrive("//host/computer/dir") returns ("//host/computer", "/dir")
Paths cannot contain both a drive letter and a UNC path.
"""
p = os.fspath(p)
if len(p) >= 2:
if isinstance(p, bytes):
sep = b'\\'
altsep = b'/'
colon = b':'
else:
sep = '\\'
altsep = '/'
colon = ':'
normp = p.replace(altsep, sep)
if (normp[0:2] == sep*2) and (normp[2:3] != sep):
# is a UNC path:
# vvvvvvvvvvvvvvvvvvvv drive letter or UNC path
# \\machine\mountpoint\directory\etc\...
# directory ^^^^^^^^^^^^^^^
index = normp.find(sep, 2)
if index == -1:
return p[:0], p
index2 = normp.find(sep, index + 1)
# a UNC path can't have two slashes in a row
# (after the initial two)
if index2 == index + 1:
return p[:0], p
if index2 == -1:
index2 = len(p)
return p[:index2], p[index2:]
if normp[1:2] == colon:
return p[:2], p[2:]
return p[:0], p
# Split a path in head (everything up to the last '/') and tail (the
# rest). After the trailing '/' is stripped, the invariant
# join(head, tail) == p holds.
# The resulting head won't end in '/' unless it is the root.
def split(p):
"""Split a pathname.
Return tuple (head, tail) where tail is everything after the final slash.
Either part may be empty."""
p = os.fspath(p)
seps = _get_bothseps(p)
d, p = splitdrive(p)
# set i to index beyond p's last slash
i = len(p)
while i and p[i-1] not in seps:
i -= 1
head, tail = p[:i], p[i:] # now tail has no slashes
# remove trailing slashes from head, unless it's all slashes
head = head.rstrip(seps) or head
return d + head, tail
# Split a path in root and extension.
# The extension is everything starting at the last dot in the last
# pathname component; the root is everything before that.
# It is always true that root + ext == p.
def splitext(p):
p = os.fspath(p)
if isinstance(p, bytes):
return genericpath._splitext(p, b'\\', b'/', b'.')
else:
return genericpath._splitext(p, '\\', '/', '.')
splitext.__doc__ = genericpath._splitext.__doc__
# Return the tail (basename) part of a path.
def basename(p):
"""Returns the final component of a pathname"""
return split(p)[1]
# Return the head (dirname) part of a path.
def dirname(p):
"""Returns the directory component of a pathname"""
return split(p)[0]
# Is a path a symbolic link?
# This will always return false on systems where os.lstat doesn't exist.
def islink(path):
"""Test whether a path is a symbolic link.
This will always return false for Windows prior to 6.0.
"""
try:
st = os.lstat(path)
except (OSError, ValueError, AttributeError):
return False
return stat.S_ISLNK(st.st_mode)
# Being true for dangling symbolic links is also useful.
def lexists(path):
"""Test whether a path exists. Returns True for broken symbolic links"""
try:
st = os.lstat(path)
except (OSError, ValueError):
return False
return True
# Is a path a mount point?
# Any drive letter root (eg c:\)
# Any share UNC (eg \\server\share)
# Any volume mounted on a filesystem folder
#
# No one method detects all three situations. Historically we've lexically
# detected drive letter roots and share UNCs. The canonical approach to
# detecting mounted volumes (querying the reparse tag) fails for the most
# common case: drive letter roots. The alternative which uses GetVolumePathName
# fails if the drive letter is the result of a SUBST.
try:
from nt import _getvolumepathname
except ImportError:
_getvolumepathname = None
def ismount(path):
"""Test whether a path is a mount point (a drive root, the root of a
share, or a mounted volume)"""
path = os.fspath(path)
seps = _get_bothseps(path)
path = abspath(path)
root, rest = splitdrive(path)
if root and root[0] in seps:
return (not rest) or (rest in seps)
if rest in seps:
return True
if _getvolumepathname:
return path.rstrip(seps) == _getvolumepathname(path).rstrip(seps)
else:
return False
# Expand paths beginning with '~' or '~user'.
# '~' means $HOME; '~user' means that user's home directory.
# If the path doesn't begin with '~', or if the user or $HOME is unknown,
# the path is returned unchanged (leaving error reporting to whatever
# function is called with the expanded path as argument).
# See also module 'glob' for expansion of *, ? and [...] in pathnames.
# (A function should also be defined to do full *sh-style environment
# variable expansion.)
def expanduser(path):
"""Expand ~ and ~user constructs.
If user or $HOME is unknown, do nothing."""
path = os.fspath(path)
if isinstance(path, bytes):
tilde = b'~'
else:
tilde = '~'
if not path.startswith(tilde):
return path
i, n = 1, len(path)
while i < n and path[i] not in _get_bothseps(path):
i += 1
if 'USERPROFILE' in os.environ:
userhome = os.environ['USERPROFILE']
elif not 'HOMEPATH' in os.environ:
return path
else:
try:
drive = os.environ['HOMEDRIVE']
except KeyError:
drive = ''
userhome = join(drive, os.environ['HOMEPATH'])
if isinstance(path, bytes):
userhome = os.fsencode(userhome)
if i != 1: #~user
userhome = join(dirname(userhome), path[1:i])
return userhome + path[i:]
# Expand paths containing shell variable substitutions.
# The following rules apply:
# - no expansion within single quotes
# - '$$' is translated into '$'
# - '%%' is translated into '%' if '%%' are not seen in %var1%%var2%
# - ${varname} is accepted.
# - $varname is accepted.
# - %varname% is accepted.
# - varnames can be made out of letters, digits and the characters '_-'
# (though is not verified in the ${varname} and %varname% cases)
# XXX With COMMAND.COM you can use any characters in a variable name,
# XXX except '^|<>='.
def expandvars(path):
"""Expand shell variables of the forms $var, ${var} and %var%.
Unknown variables are left unchanged."""
path = os.fspath(path)
if isinstance(path, bytes):
if b'$' not in path and b'%' not in path:
return path
import string
varchars = bytes(string.ascii_letters + string.digits + '_-', 'ascii')
quote = b'\''
percent = b'%'
brace = b'{'
rbrace = b'}'
dollar = b'$'
environ = getattr(os, 'environb', None)
else:
if '$' not in path and '%' not in path:
return path
import string
varchars = string.ascii_letters + string.digits + '_-'
quote = '\''
percent = '%'
brace = '{'
rbrace = '}'
dollar = '$'
environ = os.environ
res = path[:0]
index = 0
pathlen = len(path)
while index < pathlen:
c = path[index:index+1]
if c == quote: # no expansion within single quotes
path = path[index + 1:]
pathlen = len(path)
try:
index = path.index(c)
res += c + path[:index + 1]
except ValueError:
res += c + path
index = pathlen - 1
elif c == percent: # variable or '%'
if path[index + 1:index + 2] == percent:
res += c
index += 1
else:
path = path[index+1:]
pathlen = len(path)
try:
index = path.index(percent)
except ValueError:
res += percent + path
index = pathlen - 1
else:
var = path[:index]
try:
if environ is None:
value = os.fsencode(os.environ[os.fsdecode(var)])
else:
value = environ[var]
except KeyError:
value = percent + var + percent
res += value
elif c == dollar: # variable or '$$'
if path[index + 1:index + 2] == dollar:
res += c
index += 1
elif path[index + 1:index + 2] == brace:
path = path[index+2:]
pathlen = len(path)
try:
index = path.index(rbrace)
except ValueError:
res += dollar + brace + path
index = pathlen - 1
else:
var = path[:index]
try:
if environ is None:
value = os.fsencode(os.environ[os.fsdecode(var)])
else:
value = environ[var]
except KeyError:
value = dollar + brace + var + rbrace
res += value
else:
var = path[:0]
index += 1
c = path[index:index + 1]
while c and c in varchars:
var += c
index += 1
c = path[index:index + 1]
try:
if environ is None:
value = os.fsencode(os.environ[os.fsdecode(var)])
else:
value = environ[var]
except KeyError:
value = dollar + var
res += value
if c:
index -= 1
else:
res += c
index += 1
return res
# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B.
# Previously, this function also truncated pathnames to 8+3 format,
# but as this module is called "ntpath", that's obviously wrong!
def normpath(path):
"""Normalize path, eliminating double slashes, etc."""
path = os.fspath(path)
if isinstance(path, bytes):
sep = b'\\'
altsep = b'/'
curdir = b'.'
pardir = b'..'
special_prefixes = (b'\\\\.\\', b'\\\\?\\')
else:
sep = '\\'
altsep = '/'
curdir = '.'
pardir = '..'
special_prefixes = ('\\\\.\\', '\\\\?\\')
if path.startswith(special_prefixes):
# in the case of paths with these prefixes:
# \\.\ -> device names
# \\?\ -> literal paths
# do not do any normalization, but return the path unchanged
return path
path = path.replace(altsep, sep)
prefix, path = splitdrive(path)
# collapse initial backslashes
if path.startswith(sep):
prefix += sep
path = path.lstrip(sep)
comps = path.split(sep)
i = 0
while i < len(comps):
if not comps[i] or comps[i] == curdir:
del comps[i]
elif comps[i] == pardir:
if i > 0 and comps[i-1] != pardir:
del comps[i-1:i+1]
i -= 1
elif i == 0 and prefix.endswith(sep):
del comps[i]
else:
i += 1
else:
i += 1
# If the path is now empty, substitute '.'
if not prefix and not comps:
comps.append(curdir)
return prefix + sep.join(comps)
def _abspath_fallback(path):
"""Return the absolute version of a path as a fallback function in case
`nt._getfullpathname` is not available or raises OSError. See bpo-31047 for
more.
"""
path = os.fspath(path)
if not isabs(path):
if isinstance(path, bytes):
cwd = os.getcwdb()
else:
cwd = os.getcwd()
path = join(cwd, path)
return normpath(path)
# Return an absolute path.
try:
from nt import _getfullpathname
except ImportError: # not running on Windows - mock up something sensible
abspath = _abspath_fallback
else: # use native Windows method on Windows
def abspath(path):
"""Return the absolute version of a path."""
try:
return normpath(_getfullpathname(path))
except (OSError, ValueError):
return _abspath_fallback(path)
# realpath is a no-op on systems without islink support
realpath = abspath
# Win9x family and earlier have no Unicode filename support.
supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and
sys.getwindowsversion()[3] >= 2)
def relpath(path, start=None):
"""Return a relative version of a path"""
path = os.fspath(path)
if isinstance(path, bytes):
sep = b'\\'
curdir = b'.'
pardir = b'..'
else:
sep = '\\'
curdir = '.'
pardir = '..'
if start is None:
start = curdir
if not path:
raise ValueError("no path specified")
start = os.fspath(start)
try:
start_abs = abspath(normpath(start))
path_abs = abspath(normpath(path))
start_drive, start_rest = splitdrive(start_abs)
path_drive, path_rest = splitdrive(path_abs)
if normcase(start_drive) != normcase(path_drive):
raise ValueError("path is on mount %r, start on mount %r" % (
path_drive, start_drive))
start_list = [x for x in start_rest.split(sep) if x]
path_list = [x for x in path_rest.split(sep) if x]
# Work out how much of the filepath is shared by start and path.
i = 0
for e1, e2 in zip(start_list, path_list):
if normcase(e1) != normcase(e2):
break
i += 1
rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
if not rel_list:
return curdir
return join(*rel_list)
except (TypeError, ValueError, AttributeError, BytesWarning, DeprecationWarning):
genericpath._check_arg_types('relpath', path, start)
raise
# Return the longest common sub-path of the sequence of paths given as input.
# The function is case-insensitive and 'separator-insensitive', i.e. if the
# only difference between two paths is the use of '\' versus '/' as separator,
# they are deemed to be equal.
#
# However, the returned path will have the standard '\' separator (even if the
# given paths had the alternative '/' separator) and will have the case of the
# first path given in the sequence. Additionally, any trailing separator is
# stripped from the returned path.
def commonpath(paths):
"""Given a sequence of path names, returns the longest common sub-path."""
if not paths:
raise ValueError('commonpath() arg is an empty sequence')
paths = tuple(map(os.fspath, paths))
if isinstance(paths[0], bytes):
sep = b'\\'
altsep = b'/'
curdir = b'.'
else:
sep = '\\'
altsep = '/'
curdir = '.'
try:
drivesplits = [splitdrive(p.replace(altsep, sep).lower()) for p in paths]
split_paths = [p.split(sep) for d, p in drivesplits]
try:
isabs, = set(p[:1] == sep for d, p in drivesplits)
except ValueError:
raise ValueError("Can't mix absolute and relative paths") from None
# Check that all drive letters or UNC paths match. The check is made only
# now otherwise type errors for mixing strings and bytes would not be
# caught.
if len(set(d for d, p in drivesplits)) != 1:
raise ValueError("Paths don't have the same drive")
drive, path = splitdrive(paths[0].replace(altsep, sep))
common = path.split(sep)
common = [c for c in common if c and c != curdir]
split_paths = [[c for c in s if c and c != curdir] for s in split_paths]
s1 = min(split_paths)
s2 = max(split_paths)
for i, c in enumerate(s1):
if c != s2[i]:
common = common[:i]
break
else:
common = common[:len(s1)]
prefix = drive + sep if isabs else drive
return prefix + sep.join(common)
except (TypeError, AttributeError):
genericpath._check_arg_types('commonpath', *paths)
raise
# determine if two files are in fact the same file
try:
# GetFinalPathNameByHandle is available starting with Windows 6.0.
# Windows XP and non-Windows OS'es will mock _getfinalpathname.
if sys.getwindowsversion()[:2] >= (6, 0):
from nt import _getfinalpathname
else:
raise ImportError
except (AttributeError, ImportError):
# On Windows XP and earlier, two files are the same if their absolute
# pathnames are the same.
# Non-Windows operating systems fake this method with an XP
# approximation.
def _getfinalpathname(f):
return normcase(abspath(f))
try:
# The genericpath.isdir implementation uses os.stat and checks the mode
# attribute to tell whether or not the path is a directory.
# This is overkill on Windows - just pass the path to GetFileAttributes
# and check the attribute from there.
from nt import _isdir as isdir
except ImportError:
# Use genericpath.isdir as imported above.
pass

View File

@@ -1,15 +1,464 @@
"""
Operator Interface
This module exports a set of functions corresponding to the intrinsic
operators of Python. For example, operator.add(x, y) is equivalent
to the expression x+y. The function names are those used for special
methods; variants without leading and trailing '__' are also provided
for convenience.
This is the pure Python implementation of the module.
"""
__all__ = ['abs', 'add', 'and_', 'attrgetter', 'concat', 'contains', 'countOf',
'delitem', 'eq', 'floordiv', 'ge', 'getitem', 'gt', 'iadd', 'iand',
'iconcat', 'ifloordiv', 'ilshift', 'imatmul', 'imod', 'imul',
'index', 'indexOf', 'inv', 'invert', 'ior', 'ipow', 'irshift',
'is_', 'is_not', 'isub', 'itemgetter', 'itruediv', 'ixor', 'le',
'length_hint', 'lshift', 'lt', 'matmul', 'methodcaller', 'mod',
'mul', 'ne', 'neg', 'not_', 'or_', 'pos', 'pow', 'rshift',
'setitem', 'sub', 'truediv', 'truth', 'xor']
from builtins import abs as _abs
# Comparison operations:
# Comparison Operations *******************************************************#
def lt(a, b):
"Same as a < b."
return a < b
def le(a, b):
"Same as a <= b."
return a <= b
def eq(a, b):
"Same as a == b."
return a == b
def ne(a, b):
"Same as a != b."
return a != b
def ge(a, b):
"Same as a >= b."
return a >= b
def gt(a, b):
"Same as a > b."
return a > b
# Logical Operations **********************************************************#
def not_(a):
"Same as not a."
return not a
def truth(a):
"Return True if a is true, False otherwise."
return True if a else False
def is_(a, b):
"Same as a is b."
return a is b
def is_not(a, b):
"Same as a is not b."
return a is not b
# Mathematical/Bitwise Operations *********************************************#
def abs(a):
"Same as abs(a)."
return _abs(a)
def add(a, b):
"Same as a + b."
return a + b
def and_(a, b):
"Same as a & b."
return a & b
def floordiv(a, b):
"Same as a // b."
return a // b
def index(a):
"Same as a.__index__()."
return a.__index__()
def inv(a):
"Same as ~a."
return ~a
invert = inv
def lshift(a, b):
"Same as a << b."
return a << b
def mod(a, b):
"Same as a % b."
return a % b
def mul(a, b):
"Same as a * b."
return a * b
def matmul(a, b):
"Same as a @ b."
return a @ b
def neg(a):
"Same as -a."
return -a
def or_(a, b):
"Same as a | b."
return a | b
def pos(a):
"Same as +a."
return +a
def pow(a, b):
"Same as a ** b."
return a ** b
def rshift(a, b):
"Same as a >> b."
return a >> b
def sub(a, b):
"Same as a - b."
return a - b
def truediv(a, b):
"Same as a / b."
return a / b
def xor(a, b):
"Same as a ^ b."
return a ^ b
# Sequence Operations *********************************************************#
def concat(a, b):
"Same as a + b, for a and b sequences."
if not hasattr(a, '__getitem__'):
msg = "'%s' object can't be concatenated" % type(a).__name__
raise TypeError(msg)
return a + b
def contains(a, b):
"Same as b in a (note reversed operands)."
return b in a
def countOf(a, b):
"Return the number of times b occurs in a."
count = 0
for i in a:
if i == b:
count += 1
return count
def delitem(a, b):
"Same as del a[b]."
del a[b]
def getitem(a, b):
"Same as a[b]."
return a[b]
def indexOf(a, b):
"Return the first index of b in a."
for i, j in enumerate(a):
if j == b:
return i
else:
raise ValueError('sequence.index(x): x not in sequence')
def setitem(a, b, c):
"Same as a[b] = c."
a[b] = c
def length_hint(obj, default=0):
"""
Return an estimate of the number of items in obj.
This is useful for presizing containers when building from an iterable.
If the object supports len(), the result will be exact. Otherwise, it may
over- or under-estimate by an arbitrary amount. The result will be an
integer >= 0.
"""
if not isinstance(default, int):
msg = ("'%s' object cannot be interpreted as an integer" %
type(default).__name__)
raise TypeError(msg)
try:
return len(obj)
except TypeError:
pass
try:
hint = type(obj).__length_hint__
except AttributeError:
return default
try:
val = hint(obj)
except TypeError:
return default
if val is NotImplemented:
return default
if not isinstance(val, int):
msg = ('__length_hint__ must be integer, not %s' %
type(val).__name__)
raise TypeError(msg)
if val < 0:
msg = '__length_hint__() should return >= 0'
raise ValueError(msg)
return val
# Generalized Lookup Objects **************************************************#
class attrgetter:
"""
Return a callable object that fetches the given attribute(s) from its operand.
After f = attrgetter('name'), the call f(r) returns r.name.
After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).
After h = attrgetter('name.first', 'name.last'), the call h(r) returns
(r.name.first, r.name.last).
"""
__slots__ = ('_attrs', '_call')
def __init__(self, attr, *attrs):
if not attrs:
if not isinstance(attr, str):
raise TypeError('attribute name must be a string')
self._attrs = (attr,)
names = attr.split('.')
def func(obj):
for name in names:
obj = getattr(obj, name)
return obj
self._call = func
else:
self._attrs = (attr,) + attrs
getters = tuple(map(attrgetter, self._attrs))
def func(obj):
return tuple(getter(obj) for getter in getters)
self._call = func
def __call__(self, obj):
return self._call(obj)
def __repr__(self):
return '%s.%s(%s)' % (self.__class__.__module__,
self.__class__.__qualname__,
', '.join(map(repr, self._attrs)))
def __reduce__(self):
return self.__class__, self._attrs
class itemgetter:
"""
Return a callable object that fetches the given item(s) from its operand.
After f = itemgetter(2), the call f(r) returns r[2].
After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3])
"""
__slots__ = ('_items', '_call')
def __init__(self, item, *items):
if not items:
self._items = (item,)
def func(obj):
return obj[item]
self._call = func
else:
self._items = items = (item,) + items
def func(obj):
return tuple(obj[i] for i in items)
self._call = func
def __call__(self, obj):
return self._call(obj)
def __repr__(self):
return '%s.%s(%s)' % (self.__class__.__module__,
self.__class__.__name__,
', '.join(map(repr, self._items)))
def __reduce__(self):
return self.__class__, self._items
class methodcaller:
"""
Return a callable object that calls the given method on its operand.
After f = methodcaller('name'), the call f(r) returns r.name().
After g = methodcaller('name', 'date', foo=1), the call g(r) returns
r.name('date', foo=1).
"""
__slots__ = ('_name', '_args', '_kwargs')
def __init__(*args, **kwargs):
if len(args) < 2:
msg = "methodcaller needs at least one argument, the method name"
raise TypeError(msg)
self = args[0]
self._name = args[1]
if not isinstance(self._name, str):
raise TypeError('method name must be a string')
self._args = args[2:]
self._kwargs = kwargs
def __call__(self, obj):
return getattr(obj, self._name)(*self._args, **self._kwargs)
def __repr__(self):
args = [repr(self._name)]
args.extend(map(repr, self._args))
args.extend('%s=%r' % (k, v) for k, v in self._kwargs.items())
return '%s.%s(%s)' % (self.__class__.__module__,
self.__class__.__name__,
', '.join(args))
def __reduce__(self):
if not self._kwargs:
return self.__class__, (self._name,) + self._args
else:
from functools import partial
return partial(self.__class__, self._name, **self._kwargs), self._args
# In-place Operations *********************************************************#
def iadd(a, b):
"Same as a += b."
a += b
return a
def iand(a, b):
"Same as a &= b."
a &= b
return a
def iconcat(a, b):
"Same as a += b, for a and b sequences."
if not hasattr(a, '__getitem__'):
msg = "'%s' object can't be concatenated" % type(a).__name__
raise TypeError(msg)
a += b
return a
def ifloordiv(a, b):
"Same as a //= b."
a //= b
return a
def ilshift(a, b):
"Same as a <<= b."
a <<= b
return a
def imod(a, b):
"Same as a %= b."
a %= b
return a
def imul(a, b):
"Same as a *= b."
a *= b
return a
def imatmul(a, b):
"Same as a @= b."
a @= b
return a
def ior(a, b):
"Same as a |= b."
a |= b
return a
def ipow(a, b):
"Same as a **= b."
a **=b
return a
def irshift(a, b):
"Same as a >>= b."
a >>= b
return a
def isub(a, b):
"Same as a -= b."
a -= b
return a
def itruediv(a, b):
"Same as a /= b."
a /= b
return a
def ixor(a, b):
"Same as a ^= b."
a ^= b
return a
try:
from _operator import *
except ImportError:
pass
else:
from _operator import __doc__
# All of these "__func__ = func" assignments have to happen after importing
# from _operator to make sure they're set to the right function
__lt__ = lt
__le__ = le
__eq__ = eq
__ne__ = ne
__ge__ = ge
__gt__ = gt
__not__ = not_
__abs__ = abs
__add__ = add
__and__ = and_
__floordiv__ = floordiv
__index__ = index
__inv__ = inv
__invert__ = invert
__lshift__ = lshift
__mod__ = mod
__mul__ = mul
__matmul__ = matmul
__neg__ = neg
__or__ = or_
__pos__ = pos
__pow__ = pow
__rshift__ = rshift
__sub__ = sub
__truediv__ = truediv
__xor__ = xor
__concat__ = concat
__contains__ = contains
__delitem__ = delitem
__getitem__ = getitem
__setitem__ = setitem
__iadd__ = iadd
__iand__ = iand
__iconcat__ = iconcat
__ifloordiv__ = ifloordiv
__ilshift__ = ilshift
__imod__ = imod
__imul__ = imul
__imatmul__ = imatmul
__ior__ = ior
__ipow__ = ipow
__irshift__ = irshift
__isub__ = isub
__itruediv__ = itruediv
__ixor__ = ixor

135
Lib/os.py Normal file
View File

@@ -0,0 +1,135 @@
import sys
from _os import *
if name == 'nt':
linesep = '\r\n'
import ntpath as path
else:
linesep = '\n'
import posixpath as path
sys.modules['os.path'] = path
from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep,
devnull)
# Change environ to automatically call putenv(), unsetenv if they exist.
from _collections_abc import MutableMapping
class _Environ(MutableMapping):
def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue, putenv, unsetenv):
self.encodekey = encodekey
self.decodekey = decodekey
self.encodevalue = encodevalue
self.decodevalue = decodevalue
self.putenv = putenv
self.unsetenv = unsetenv
self._data = data
def __getitem__(self, key):
try:
value = self._data[self.encodekey(key)]
except KeyError:
# raise KeyError with the original key value
raise KeyError(key) from None
return self.decodevalue(value)
def __setitem__(self, key, value):
key = self.encodekey(key)
value = self.encodevalue(value)
self.putenv(key, value)
self._data[key] = value
def __delitem__(self, key):
encodedkey = self.encodekey(key)
self.unsetenv(encodedkey)
try:
del self._data[encodedkey]
except KeyError:
# raise KeyError with the original key value
raise KeyError(key) from None
def __iter__(self):
# list() from dict object is an atomic operation
keys = list(self._data)
for key in keys:
yield self.decodekey(key)
def __len__(self):
return len(self._data)
def __repr__(self):
return 'environ({{{}}})'.format(', '.join(
('{!r}: {!r}'.format(self.decodekey(key), self.decodevalue(value))
for key, value in self._data.items())))
def copy(self):
return dict(self)
def setdefault(self, key, value):
if key not in self:
self[key] = value
return self[key]
try:
_putenv = putenv
except NameError:
_putenv = lambda key, value: None
# else:
# if "putenv" not in __all__:
# __all__.append("putenv")
try:
_unsetenv = unsetenv
except NameError:
_unsetenv = lambda key: _putenv(key, "")
# else:
# if "unsetenv" not in __all__:
# __all__.append("unsetenv")
def _createenviron():
# if name == 'nt':
# # Where Env Var Names Must Be UPPERCASE
# def check_str(value):
# if not isinstance(value, str):
# raise TypeError("str expected, not %s" % type(value).__name__)
# return value
# encode = check_str
# decode = str
# def encodekey(key):
# return encode(key).upper()
# data = {}
# for key, value in environ.items():
# data[encodekey(key)] = value
# else:
# # Where Env Var Names Can Be Mixed Case
# encoding = sys.getfilesystemencoding()
# def encode(value):
# if not isinstance(value, str):
# raise TypeError("str expected, not %s" % type(value).__name__)
# return value.encode(encoding, 'surrogateescape')
# def decode(value):
# return value.decode(encoding, 'surrogateescape')
# encodekey = encode
decode = str
encode = str
encodekey = encode
data = environ
return _Environ(data,
encodekey, decode,
encode, decode,
_putenv, _unsetenv)
# unicode environ
environ = _createenviron()
del _createenviron
def getenv(key, default=None):
"""Get an environment variable, return None if it doesn't exist.
The optional second argument can specify an alternate default.
key, default and the result are str."""
return environ.get(key, default)

525
Lib/posixpath.py Normal file
View File

@@ -0,0 +1,525 @@
"""Common operations on Posix pathnames.
Instead of importing this module directly, import os and refer to
this module as os.path. The "os.path" name is an alias for this
module on Posix systems; on other systems (e.g. Windows),
os.path provides the same operations in a manner specific to that
platform, and is an alias to another module (e.g. ntpath).
Some of this can actually be useful on non-Posix systems too, e.g.
for manipulation of the pathname component of URLs.
"""
# Strings representing various path-related bits and pieces.
# These are primarily for export; internally, they are hardcoded.
# Should be set before imports for resolving cyclic dependency.
curdir = '.'
pardir = '..'
extsep = '.'
sep = '/'
pathsep = ':'
defpath = '/bin:/usr/bin'
altsep = None
devnull = '/dev/null'
import os
import sys
import stat
import genericpath
from genericpath import *
__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
"basename","dirname","commonprefix","getsize","getmtime",
"getatime","getctime","islink","exists","lexists","isdir","isfile",
"ismount", "expanduser","expandvars","normpath","abspath",
"samefile","sameopenfile","samestat",
"curdir","pardir","sep","pathsep","defpath","altsep","extsep",
"devnull","realpath","supports_unicode_filenames","relpath",
"commonpath"]
def _get_sep(path):
if isinstance(path, bytes):
return b'/'
else:
return '/'
# Normalize the case of a pathname. Trivial in Posix, string.lower on Mac.
# On MS-DOS this may also turn slashes into backslashes; however, other
# normalizations (such as optimizing '../' away) are not allowed
# (another function should be defined to do that).
def normcase(s):
"""Normalize case of pathname. Has no effect under Posix"""
return os.fspath(s)
# Return whether a path is absolute.
# Trivial in Posix, harder on the Mac or MS-DOS.
def isabs(s):
"""Test whether a path is absolute"""
s = os.fspath(s)
sep = _get_sep(s)
return s.startswith(sep)
# Join pathnames.
# Ignore the previous parts if a part is absolute.
# Insert a '/' unless the first part is empty or already ends in '/'.
def join(a, *p):
"""Join two or more pathname components, inserting '/' as needed.
If any component is an absolute path, all previous path components
will be discarded. An empty last part will result in a path that
ends with a separator."""
a = os.fspath(a)
sep = _get_sep(a)
path = a
try:
if not p:
path[:0] + sep #23780: Ensure compatible data type even if p is null.
for b in map(os.fspath, p):
if b.startswith(sep):
path = b
elif not path or path.endswith(sep):
path += b
else:
path += sep + b
except (TypeError, AttributeError, BytesWarning):
genericpath._check_arg_types('join', a, *p)
raise
return path
# Split a path in head (everything up to the last '/') and tail (the
# rest). If the path ends in '/', tail will be empty. If there is no
# '/' in the path, head will be empty.
# Trailing '/'es are stripped from head unless it is the root.
def split(p):
"""Split a pathname. Returns tuple "(head, tail)" where "tail" is
everything after the final slash. Either part may be empty."""
p = os.fspath(p)
sep = _get_sep(p)
i = p.rfind(sep) + 1
head, tail = p[:i], p[i:]
if head and head != sep*len(head):
head = head.rstrip(sep)
return head, tail
# Split a path in root and extension.
# The extension is everything starting at the last dot in the last
# pathname component; the root is everything before that.
# It is always true that root + ext == p.
def splitext(p):
p = os.fspath(p)
if isinstance(p, bytes):
sep = b'/'
extsep = b'.'
else:
sep = '/'
extsep = '.'
return genericpath._splitext(p, sep, None, extsep)
splitext.__doc__ = genericpath._splitext.__doc__
# Split a pathname into a drive specification and the rest of the
# path. Useful on DOS/Windows/NT; on Unix, the drive is always empty.
def splitdrive(p):
"""Split a pathname into drive and path. On Posix, drive is always
empty."""
p = os.fspath(p)
return p[:0], p
# Return the tail (basename) part of a path, same as split(path)[1].
def basename(p):
"""Returns the final component of a pathname"""
p = os.fspath(p)
sep = _get_sep(p)
i = p.rfind(sep) + 1
return p[i:]
# Return the head (dirname) part of a path, same as split(path)[0].
def dirname(p):
"""Returns the directory component of a pathname"""
p = os.fspath(p)
sep = _get_sep(p)
i = p.rfind(sep) + 1
head = p[:i]
if head and head != sep*len(head):
head = head.rstrip(sep)
return head
# Is a path a symbolic link?
# This will always return false on systems where os.lstat doesn't exist.
def islink(path):
"""Test whether a path is a symbolic link"""
try:
st = os.lstat(path)
except (OSError, ValueError, AttributeError):
return False
return stat.S_ISLNK(st.st_mode)
# Being true for dangling symbolic links is also useful.
def lexists(path):
"""Test whether a path exists. Returns True for broken symbolic links"""
try:
os.lstat(path)
except (OSError, ValueError):
return False
return True
# Is a path a mount point?
# (Does this work for all UNIXes? Is it even guaranteed to work by Posix?)
def ismount(path):
"""Test whether a path is a mount point"""
try:
s1 = os.lstat(path)
except (OSError, ValueError):
# It doesn't exist -- so not a mount point. :-)
return False
else:
# A symlink can never be a mount point
if stat.S_ISLNK(s1.st_mode):
return False
if isinstance(path, bytes):
parent = join(path, b'..')
else:
parent = join(path, '..')
parent = realpath(parent)
try:
s2 = os.lstat(parent)
except (OSError, ValueError):
return False
dev1 = s1.st_dev
dev2 = s2.st_dev
if dev1 != dev2:
return True # path/.. on a different device as path
ino1 = s1.st_ino
ino2 = s2.st_ino
if ino1 == ino2:
return True # path/.. is the same i-node as path
return False
# Expand paths beginning with '~' or '~user'.
# '~' means $HOME; '~user' means that user's home directory.
# If the path doesn't begin with '~', or if the user or $HOME is unknown,
# the path is returned unchanged (leaving error reporting to whatever
# function is called with the expanded path as argument).
# See also module 'glob' for expansion of *, ? and [...] in pathnames.
# (A function should also be defined to do full *sh-style environment
# variable expansion.)
def expanduser(path):
"""Expand ~ and ~user constructions. If user or $HOME is unknown,
do nothing."""
path = os.fspath(path)
if isinstance(path, bytes):
tilde = b'~'
else:
tilde = '~'
if not path.startswith(tilde):
return path
sep = _get_sep(path)
i = path.find(sep, 1)
if i < 0:
i = len(path)
if i == 1:
if 'HOME' not in os.environ:
import pwd
try:
userhome = pwd.getpwuid(os.getuid()).pw_dir
except KeyError:
# bpo-10496: if the current user identifier doesn't exist in the
# password database, return the path unchanged
return path
else:
userhome = os.environ['HOME']
else:
import pwd
name = path[1:i]
if isinstance(name, bytes):
name = str(name, 'ASCII')
try:
pwent = pwd.getpwnam(name)
except KeyError:
# bpo-10496: if the user name from the path doesn't exist in the
# password database, return the path unchanged
return path
userhome = pwent.pw_dir
if isinstance(path, bytes):
userhome = os.fsencode(userhome)
root = b'/'
else:
root = '/'
userhome = userhome.rstrip(root)
return (userhome + path[i:]) or root
# Expand paths containing shell variable substitutions.
# This expands the forms $variable and ${variable} only.
# Non-existent variables are left unchanged.
_varprog = None
_varprogb = None
def expandvars(path):
"""Expand shell variables of form $var and ${var}. Unknown variables
are left unchanged."""
path = os.fspath(path)
global _varprog, _varprogb
if isinstance(path, bytes):
if b'$' not in path:
return path
if not _varprogb:
import re
_varprogb = re.compile(br'\$(\w+|\{[^}]*\})', re.ASCII)
search = _varprogb.search
start = b'{'
end = b'}'
environ = getattr(os, 'environb', None)
else:
if '$' not in path:
return path
if not _varprog:
import re
_varprog = re.compile(r'\$(\w+|\{[^}]*\})', re.ASCII)
search = _varprog.search
start = '{'
end = '}'
environ = os.environ
i = 0
while True:
m = search(path, i)
if not m:
break
i, j = m.span(0)
name = m.group(1)
if name.startswith(start) and name.endswith(end):
name = name[1:-1]
try:
if environ is None:
value = os.fsencode(os.environ[os.fsdecode(name)])
else:
value = environ[name]
except KeyError:
i = j
else:
tail = path[j:]
path = path[:i] + value
i = len(path)
path += tail
return path
# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
# It should be understood that this may change the meaning of the path
# if it contains symbolic links!
def normpath(path):
"""Normalize path, eliminating double slashes, etc."""
path = os.fspath(path)
if isinstance(path, bytes):
sep = b'/'
empty = b''
dot = b'.'
dotdot = b'..'
else:
sep = '/'
empty = ''
dot = '.'
dotdot = '..'
if path == empty:
return dot
initial_slashes = path.startswith(sep)
# POSIX allows one or two initial slashes, but treats three or more
# as single slash.
if (initial_slashes and
path.startswith(sep*2) and not path.startswith(sep*3)):
initial_slashes = 2
comps = path.split(sep)
new_comps = []
for comp in comps:
if comp in (empty, dot):
continue
if (comp != dotdot or (not initial_slashes and not new_comps) or
(new_comps and new_comps[-1] == dotdot)):
new_comps.append(comp)
elif new_comps:
new_comps.pop()
comps = new_comps
path = sep.join(comps)
if initial_slashes:
path = sep*initial_slashes + path
return path or dot
def abspath(path):
"""Return an absolute path."""
path = os.fspath(path)
if not isabs(path):
if isinstance(path, bytes):
cwd = os.getcwdb()
else:
cwd = os.getcwd()
path = join(cwd, path)
return normpath(path)
# Return a canonical path (i.e. the absolute location of a file on the
# filesystem).
def realpath(filename):
"""Return the canonical path of the specified filename, eliminating any
symbolic links encountered in the path."""
filename = os.fspath(filename)
path, ok = _joinrealpath(filename[:0], filename, {})
return abspath(path)
# Join two paths, normalizing and eliminating any symbolic links
# encountered in the second path.
def _joinrealpath(path, rest, seen):
if isinstance(path, bytes):
sep = b'/'
curdir = b'.'
pardir = b'..'
else:
sep = '/'
curdir = '.'
pardir = '..'
if isabs(rest):
rest = rest[1:]
path = sep
while rest:
name, _, rest = rest.partition(sep)
if not name or name == curdir:
# current dir
continue
if name == pardir:
# parent dir
if path:
path, name = split(path)
if name == pardir:
path = join(path, pardir, pardir)
else:
path = pardir
continue
newpath = join(path, name)
if not islink(newpath):
path = newpath
continue
# Resolve the symbolic link
if newpath in seen:
# Already seen this path
path = seen[newpath]
if path is not None:
# use cached value
continue
# The symlink is not resolved, so we must have a symlink loop.
# Return already resolved part + rest of the path unchanged.
return join(newpath, rest), False
seen[newpath] = None # not resolved symlink
path, ok = _joinrealpath(path, os.readlink(newpath), seen)
if not ok:
return join(path, rest), False
seen[newpath] = path # resolved symlink
return path, True
supports_unicode_filenames = (sys.platform == 'darwin')
def relpath(path, start=None):
"""Return a relative version of a path"""
if not path:
raise ValueError("no path specified")
path = os.fspath(path)
if isinstance(path, bytes):
curdir = b'.'
sep = b'/'
pardir = b'..'
else:
curdir = '.'
sep = '/'
pardir = '..'
if start is None:
start = curdir
else:
start = os.fspath(start)
try:
start_list = [x for x in abspath(start).split(sep) if x]
path_list = [x for x in abspath(path).split(sep) if x]
# Work out how much of the filepath is shared by start and path.
i = len(commonprefix([start_list, path_list]))
rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
if not rel_list:
return curdir
return join(*rel_list)
except (TypeError, AttributeError, BytesWarning, DeprecationWarning):
genericpath._check_arg_types('relpath', path, start)
raise
# Return the longest common sub-path of the sequence of paths given as input.
# The paths are not normalized before comparing them (this is the
# responsibility of the caller). Any trailing separator is stripped from the
# returned path.
def commonpath(paths):
"""Given a sequence of path names, returns the longest common sub-path."""
if not paths:
raise ValueError('commonpath() arg is an empty sequence')
paths = tuple(map(os.fspath, paths))
if isinstance(paths[0], bytes):
sep = b'/'
curdir = b'.'
else:
sep = '/'
curdir = '.'
try:
split_paths = [path.split(sep) for path in paths]
try:
isabs, = set(p[:1] == sep for p in paths)
except ValueError:
raise ValueError("Can't mix absolute and relative paths") from None
split_paths = [[c for c in s if c and c != curdir] for s in split_paths]
s1 = min(split_paths)
s2 = max(split_paths)
common = s1
for i, c in enumerate(s1):
if c != s2[i]:
common = s1[:i]
break
prefix = sep if isabs else sep[:0]
return prefix + sep.join(common)
except (TypeError, AttributeError):
genericpath._check_arg_types('commonpath', *paths)
raise

View File

@@ -1,11 +0,0 @@
""" Regular expressions """
def match(pattern, string, flags=0):
return _compile(pattern, flags).match(string)
def _compile(pattern, flags):
p = sre_compile.compile(pattern, flags)
return p

161
Lib/reprlib.py Normal file
View File

@@ -0,0 +1,161 @@
"""Redo the builtin repr() (representation) but with limits on most sizes."""
__all__ = ["Repr", "repr", "recursive_repr"]
import builtins
from itertools import islice
from _thread import get_ident
def recursive_repr(fillvalue='...'):
'Decorator to make a repr function return fillvalue for a recursive call'
def decorating_function(user_function):
repr_running = set()
def wrapper(self):
key = id(self), get_ident()
if key in repr_running:
return fillvalue
repr_running.add(key)
try:
result = user_function(self)
finally:
repr_running.discard(key)
return result
# Can't use functools.wraps() here because of bootstrap issues
wrapper.__module__ = getattr(user_function, '__module__')
wrapper.__doc__ = getattr(user_function, '__doc__')
wrapper.__name__ = getattr(user_function, '__name__')
wrapper.__qualname__ = getattr(user_function, '__qualname__')
wrapper.__annotations__ = getattr(user_function, '__annotations__', {})
return wrapper
return decorating_function
class Repr:
def __init__(self):
self.maxlevel = 6
self.maxtuple = 6
self.maxlist = 6
self.maxarray = 5
self.maxdict = 4
self.maxset = 6
self.maxfrozenset = 6
self.maxdeque = 6
self.maxstring = 30
self.maxlong = 40
self.maxother = 30
def repr(self, x):
return self.repr1(x, self.maxlevel)
def repr1(self, x, level):
typename = type(x).__name__
if ' ' in typename:
parts = typename.split()
typename = '_'.join(parts)
if hasattr(self, 'repr_' + typename):
return getattr(self, 'repr_' + typename)(x, level)
else:
return self.repr_instance(x, level)
def _repr_iterable(self, x, level, left, right, maxiter, trail=''):
n = len(x)
if level <= 0 and n:
s = '...'
else:
newlevel = level - 1
repr1 = self.repr1
pieces = [repr1(elem, newlevel) for elem in islice(x, maxiter)]
if n > maxiter: pieces.append('...')
s = ', '.join(pieces)
if n == 1 and trail: right = trail + right
return '%s%s%s' % (left, s, right)
def repr_tuple(self, x, level):
return self._repr_iterable(x, level, '(', ')', self.maxtuple, ',')
def repr_list(self, x, level):
return self._repr_iterable(x, level, '[', ']', self.maxlist)
def repr_array(self, x, level):
if not x:
return "array('%s')" % x.typecode
header = "array('%s', [" % x.typecode
return self._repr_iterable(x, level, header, '])', self.maxarray)
def repr_set(self, x, level):
if not x:
return 'set()'
x = _possibly_sorted(x)
return self._repr_iterable(x, level, '{', '}', self.maxset)
def repr_frozenset(self, x, level):
if not x:
return 'frozenset()'
x = _possibly_sorted(x)
return self._repr_iterable(x, level, 'frozenset({', '})',
self.maxfrozenset)
def repr_deque(self, x, level):
return self._repr_iterable(x, level, 'deque([', '])', self.maxdeque)
def repr_dict(self, x, level):
n = len(x)
if n == 0: return '{}'
if level <= 0: return '{...}'
newlevel = level - 1
repr1 = self.repr1
pieces = []
for key in islice(_possibly_sorted(x), self.maxdict):
keyrepr = repr1(key, newlevel)
valrepr = repr1(x[key], newlevel)
pieces.append('%s: %s' % (keyrepr, valrepr))
if n > self.maxdict: pieces.append('...')
s = ', '.join(pieces)
return '{%s}' % (s,)
def repr_str(self, x, level):
s = builtins.repr(x[:self.maxstring])
if len(s) > self.maxstring:
i = max(0, (self.maxstring-3)//2)
j = max(0, self.maxstring-3-i)
s = builtins.repr(x[:i] + x[len(x)-j:])
s = s[:i] + '...' + s[len(s)-j:]
return s
def repr_int(self, x, level):
s = builtins.repr(x) # XXX Hope this isn't too slow...
if len(s) > self.maxlong:
i = max(0, (self.maxlong-3)//2)
j = max(0, self.maxlong-3-i)
s = s[:i] + '...' + s[len(s)-j:]
return s
def repr_instance(self, x, level):
try:
s = builtins.repr(x)
# Bugs in x.__repr__() can cause arbitrary
# exceptions -- then make up something
except Exception:
return '<%s instance at %#x>' % (x.__class__.__name__, id(x))
if len(s) > self.maxother:
i = max(0, (self.maxother-3)//2)
j = max(0, self.maxother-3-i)
s = s[:i] + '...' + s[len(s)-j:]
return s
def _possibly_sorted(x):
# Since not all sequences of items can be sorted and comparison
# functions may raise arbitrary exceptions, return an unsorted
# sequence in that case.
try:
return sorted(x)
except Exception:
return list(x)
aRepr = Repr()
repr = aRepr.repr

179
Lib/stat.py Normal file
View File

@@ -0,0 +1,179 @@
"""Constants/functions for interpreting results of os.stat() and os.lstat().
Suggested usage: from stat import *
"""
# Indices for stat struct members in the tuple returned by os.stat()
ST_MODE = 0
ST_INO = 1
ST_DEV = 2
ST_NLINK = 3
ST_UID = 4
ST_GID = 5
ST_SIZE = 6
ST_ATIME = 7
ST_MTIME = 8
ST_CTIME = 9
# Extract bits from the mode
def S_IMODE(mode):
"""Return the portion of the file's mode that can be set by
os.chmod().
"""
return mode & 0o7777
def S_IFMT(mode):
"""Return the portion of the file's mode that describes the
file type.
"""
return mode & 0o170000
# Constants used as S_IFMT() for various file types
# (not all are implemented on all systems)
S_IFDIR = 0o040000 # directory
S_IFCHR = 0o020000 # character device
S_IFBLK = 0o060000 # block device
S_IFREG = 0o100000 # regular file
S_IFIFO = 0o010000 # fifo (named pipe)
S_IFLNK = 0o120000 # symbolic link
S_IFSOCK = 0o140000 # socket file
# Functions to test for each file type
def S_ISDIR(mode):
"""Return True if mode is from a directory."""
return S_IFMT(mode) == S_IFDIR
def S_ISCHR(mode):
"""Return True if mode is from a character special device file."""
return S_IFMT(mode) == S_IFCHR
def S_ISBLK(mode):
"""Return True if mode is from a block special device file."""
return S_IFMT(mode) == S_IFBLK
def S_ISREG(mode):
"""Return True if mode is from a regular file."""
return S_IFMT(mode) == S_IFREG
def S_ISFIFO(mode):
"""Return True if mode is from a FIFO (named pipe)."""
return S_IFMT(mode) == S_IFIFO
def S_ISLNK(mode):
"""Return True if mode is from a symbolic link."""
return S_IFMT(mode) == S_IFLNK
def S_ISSOCK(mode):
"""Return True if mode is from a socket."""
return S_IFMT(mode) == S_IFSOCK
# Names for permission bits
S_ISUID = 0o4000 # set UID bit
S_ISGID = 0o2000 # set GID bit
S_ENFMT = S_ISGID # file locking enforcement
S_ISVTX = 0o1000 # sticky bit
S_IREAD = 0o0400 # Unix V7 synonym for S_IRUSR
S_IWRITE = 0o0200 # Unix V7 synonym for S_IWUSR
S_IEXEC = 0o0100 # Unix V7 synonym for S_IXUSR
S_IRWXU = 0o0700 # mask for owner permissions
S_IRUSR = 0o0400 # read by owner
S_IWUSR = 0o0200 # write by owner
S_IXUSR = 0o0100 # execute by owner
S_IRWXG = 0o0070 # mask for group permissions
S_IRGRP = 0o0040 # read by group
S_IWGRP = 0o0020 # write by group
S_IXGRP = 0o0010 # execute by group
S_IRWXO = 0o0007 # mask for others (not in group) permissions
S_IROTH = 0o0004 # read by others
S_IWOTH = 0o0002 # write by others
S_IXOTH = 0o0001 # execute by others
# Names for file flags
UF_NODUMP = 0x00000001 # do not dump file
UF_IMMUTABLE = 0x00000002 # file may not be changed
UF_APPEND = 0x00000004 # file may only be appended to
UF_OPAQUE = 0x00000008 # directory is opaque when viewed through a union stack
UF_NOUNLINK = 0x00000010 # file may not be renamed or deleted
UF_COMPRESSED = 0x00000020 # OS X: file is hfs-compressed
UF_HIDDEN = 0x00008000 # OS X: file should not be displayed
SF_ARCHIVED = 0x00010000 # file may be archived
SF_IMMUTABLE = 0x00020000 # file may not be changed
SF_APPEND = 0x00040000 # file may only be appended to
SF_NOUNLINK = 0x00100000 # file may not be renamed or deleted
SF_SNAPSHOT = 0x00200000 # file is a snapshot file
_filemode_table = (
((S_IFLNK, "l"),
(S_IFSOCK, "s"), # Must appear before IFREG and IFDIR as IFSOCK == IFREG | IFDIR
(S_IFREG, "-"),
(S_IFBLK, "b"),
(S_IFDIR, "d"),
(S_IFCHR, "c"),
(S_IFIFO, "p")),
((S_IRUSR, "r"),),
((S_IWUSR, "w"),),
((S_IXUSR|S_ISUID, "s"),
(S_ISUID, "S"),
(S_IXUSR, "x")),
((S_IRGRP, "r"),),
((S_IWGRP, "w"),),
((S_IXGRP|S_ISGID, "s"),
(S_ISGID, "S"),
(S_IXGRP, "x")),
((S_IROTH, "r"),),
((S_IWOTH, "w"),),
((S_IXOTH|S_ISVTX, "t"),
(S_ISVTX, "T"),
(S_IXOTH, "x"))
)
def filemode(mode):
"""Convert a file's mode to a string of the form '-rwxrwxrwx'."""
perm = []
for table in _filemode_table:
for bit, char in table:
if mode & bit == bit:
perm.append(char)
break
else:
perm.append("-")
return "".join(perm)
# Windows FILE_ATTRIBUTE constants for interpreting os.stat()'s
# "st_file_attributes" member
FILE_ATTRIBUTE_ARCHIVE = 32
FILE_ATTRIBUTE_COMPRESSED = 2048
FILE_ATTRIBUTE_DEVICE = 64
FILE_ATTRIBUTE_DIRECTORY = 16
FILE_ATTRIBUTE_ENCRYPTED = 16384
FILE_ATTRIBUTE_HIDDEN = 2
FILE_ATTRIBUTE_INTEGRITY_STREAM = 32768
FILE_ATTRIBUTE_NORMAL = 128
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192
FILE_ATTRIBUTE_NO_SCRUB_DATA = 131072
FILE_ATTRIBUTE_OFFLINE = 4096
FILE_ATTRIBUTE_READONLY = 1
FILE_ATTRIBUTE_REPARSE_POINT = 1024
FILE_ATTRIBUTE_SPARSE_FILE = 512
FILE_ATTRIBUTE_SYSTEM = 4
FILE_ATTRIBUTE_TEMPORARY = 256
FILE_ATTRIBUTE_VIRTUAL = 65536
# If available, use C implementation
try:
from _stat import *
except ImportError:
pass

28
Lib/this.py Normal file
View File

@@ -0,0 +1,28 @@
s = """Gur Mra bs Clguba, ol Gvz Crgref
Ornhgvshy vf orggre guna htyl.
Rkcyvpvg vf orggre guna vzcyvpvg.
Fvzcyr vf orggre guna pbzcyrk.
Pbzcyrk vf orggre guna pbzcyvpngrq.
Syng vf orggre guna arfgrq.
Fcnefr vf orggre guna qrafr.
Ernqnovyvgl pbhagf.
Fcrpvny pnfrf nera'g fcrpvny rabhtu gb oernx gur ehyrf.
Nygubhtu cenpgvpnyvgl orngf chevgl.
Reebef fubhyq arire cnff fvyragyl.
Hayrff rkcyvpvgyl fvyraprq.
Va gur snpr bs nzovthvgl, ershfr gur grzcgngvba gb thrff.
Gurer fubhyq or bar-- naq cersrenoyl bayl bar --boivbhf jnl gb qb vg.
Nygubhtu gung jnl znl abg or boivbhf ng svefg hayrff lbh'er Qhgpu.
Abj vf orggre guna arire.
Nygubhtu arire vf bsgra orggre guna *evtug* abj.
Vs gur vzcyrzragngvba vf uneq gb rkcynva, vg'f n onq vqrn.
Vs gur vzcyrzragngvba vf rnfl gb rkcynva, vg znl or n tbbq vqrn.
Anzrfcnprf ner bar ubaxvat terng vqrn -- yrg'f qb zber bs gubfr!"""
d = {}
for c in (65, 97):
for i in range(26):
d[chr(i+c)] = chr((i+13) % 26 + c)
print("".join([d.get(c, c) for c in s]))

295
Lib/types.py Normal file
View File

@@ -0,0 +1,295 @@
"""
Define names for built-in types that aren't directly accessible as a builtin.
"""
import sys
# Iterators in Python aren't a matter of type but of protocol. A large
# and changing number of builtin types implement *some* flavor of
# iterator. Don't check the type! Use hasattr to check for both
# "__iter__" and "__next__" attributes instead.
def _f(): pass
FunctionType = type(_f)
LambdaType = type(lambda: None) # Same as FunctionType
CodeType = type(_f.__code__)
MappingProxyType = type(type.__dict__)
SimpleNamespace = type(sys.implementation)
def _g():
yield 1
GeneratorType = type(_g())
# async def _c(): pass
# _c = _c()
# CoroutineType = type(_c)
# _c.close() # Prevent ResourceWarning
# async def _ag():
# yield
# _ag = _ag()
# AsyncGeneratorType = type(_ag)
class _C:
def _m(self): pass
MethodType = type(_C()._m)
BuiltinFunctionType = type(len)
BuiltinMethodType = type([].append) # Same as BuiltinFunctionType
WrapperDescriptorType = type(object.__init__)
MethodWrapperType = type(object().__str__)
MethodDescriptorType = type(str.join)
ClassMethodDescriptorType = type(dict.__dict__['fromkeys'])
ModuleType = type(sys)
# try:
# raise TypeError
# except TypeError:
# tb = sys.exc_info()[2]
# TracebackType = type(tb)
# FrameType = type(tb.tb_frame)
# tb = None; del tb
# For Jython, the following two types are identical
GetSetDescriptorType = type(FunctionType.__code__)
# MemberDescriptorType = type(FunctionType.__globals__)
del sys, _f, _g, _C # Not for export
# Provide a PEP 3115 compliant mechanism for class creation
def new_class(name, bases=(), kwds=None, exec_body=None):
"""Create a class object dynamically using the appropriate metaclass."""
resolved_bases = resolve_bases(bases)
meta, ns, kwds = prepare_class(name, resolved_bases, kwds)
if exec_body is not None:
exec_body(ns)
if resolved_bases is not bases:
ns['__orig_bases__'] = bases
return meta(name, resolved_bases, ns, **kwds)
def resolve_bases(bases):
"""Resolve MRO entries dynamically as specified by PEP 560."""
new_bases = list(bases)
updated = False
shift = 0
for i, base in enumerate(bases):
if isinstance(base, type):
continue
if not hasattr(base, "__mro_entries__"):
continue
new_base = base.__mro_entries__(bases)
updated = True
if not isinstance(new_base, tuple):
raise TypeError("__mro_entries__ must return a tuple")
else:
new_bases[i+shift:i+shift+1] = new_base
shift += len(new_base) - 1
if not updated:
return bases
return tuple(new_bases)
def prepare_class(name, bases=(), kwds=None):
"""Call the __prepare__ method of the appropriate metaclass.
Returns (metaclass, namespace, kwds) as a 3-tuple
*metaclass* is the appropriate metaclass
*namespace* is the prepared class namespace
*kwds* is an updated copy of the passed in kwds argument with any
'metaclass' entry removed. If no kwds argument is passed in, this will
be an empty dict.
"""
if kwds is None:
kwds = {}
else:
kwds = dict(kwds) # Don't alter the provided mapping
if 'metaclass' in kwds:
meta = kwds.pop('metaclass')
else:
if bases:
meta = type(bases[0])
else:
meta = type
if isinstance(meta, type):
# when meta is a type, we first determine the most-derived metaclass
# instead of invoking the initial candidate directly
meta = _calculate_meta(meta, bases)
if hasattr(meta, '__prepare__'):
ns = meta.__prepare__(name, bases, **kwds)
else:
ns = {}
return meta, ns, kwds
def _calculate_meta(meta, bases):
"""Calculate the most derived metaclass."""
winner = meta
for base in bases:
base_meta = type(base)
if issubclass(winner, base_meta):
continue
if issubclass(base_meta, winner):
winner = base_meta
continue
# else:
raise TypeError("metaclass conflict: "
"the metaclass of a derived class "
"must be a (non-strict) subclass "
"of the metaclasses of all its bases")
return winner
class DynamicClassAttribute:
"""Route attribute access on a class to __getattr__.
This is a descriptor, used to define attributes that act differently when
accessed through an instance and through a class. Instance access remains
normal, but access to an attribute through a class will be routed to the
class's __getattr__ method; this is done by raising AttributeError.
This allows one to have properties active on an instance, and have virtual
attributes on the class with the same name (see Enum for an example).
"""
def __init__(self, fget=None, fset=None, fdel=None, doc=None):
self.fget = fget
self.fset = fset
self.fdel = fdel
# next two lines make DynamicClassAttribute act the same as property
self.__doc__ = doc or fget.__doc__
self.overwrite_doc = doc is None
# support for abstract methods
self.__isabstractmethod__ = bool(getattr(fget, '__isabstractmethod__', False))
def __get__(self, instance, ownerclass=None):
if instance is None:
if self.__isabstractmethod__:
return self
raise AttributeError()
elif self.fget is None:
raise AttributeError("unreadable attribute")
return self.fget(instance)
def __set__(self, instance, value):
if self.fset is None:
raise AttributeError("can't set attribute")
self.fset(instance, value)
def __delete__(self, instance):
if self.fdel is None:
raise AttributeError("can't delete attribute")
self.fdel(instance)
def getter(self, fget):
fdoc = fget.__doc__ if self.overwrite_doc else None
result = type(self)(fget, self.fset, self.fdel, fdoc or self.__doc__)
result.overwrite_doc = self.overwrite_doc
return result
def setter(self, fset):
result = type(self)(self.fget, fset, self.fdel, self.__doc__)
result.overwrite_doc = self.overwrite_doc
return result
def deleter(self, fdel):
result = type(self)(self.fget, self.fset, fdel, self.__doc__)
result.overwrite_doc = self.overwrite_doc
return result
class _GeneratorWrapper:
# TODO: Implement this in C.
def __init__(self, gen):
self.__wrapped = gen
self.__isgen = gen.__class__ is GeneratorType
self.__name__ = getattr(gen, '__name__', None)
self.__qualname__ = getattr(gen, '__qualname__', None)
def send(self, val):
return self.__wrapped.send(val)
def throw(self, tp, *rest):
return self.__wrapped.throw(tp, *rest)
def close(self):
return self.__wrapped.close()
@property
def gi_code(self):
return self.__wrapped.gi_code
@property
def gi_frame(self):
return self.__wrapped.gi_frame
@property
def gi_running(self):
return self.__wrapped.gi_running
@property
def gi_yieldfrom(self):
return self.__wrapped.gi_yieldfrom
cr_code = gi_code
cr_frame = gi_frame
cr_running = gi_running
cr_await = gi_yieldfrom
def __next__(self):
return next(self.__wrapped)
def __iter__(self):
if self.__isgen:
return self.__wrapped
return self
__await__ = __iter__
def coroutine(func):
"""Convert regular generator function to a coroutine."""
if not callable(func):
raise TypeError('types.coroutine() expects a callable')
if (func.__class__ is FunctionType and
getattr(func, '__code__', None).__class__ is CodeType):
co_flags = func.__code__.co_flags
# Check if 'func' is a coroutine function.
# (0x180 == CO_COROUTINE | CO_ITERABLE_COROUTINE)
if co_flags & 0x180:
return func
# Check if 'func' is a generator function.
# (0x20 == CO_GENERATOR)
if co_flags & 0x20:
# TODO: Implement this in C.
co = func.__code__
func.__code__ = CodeType(
co.co_argcount, co.co_kwonlyargcount, co.co_nlocals,
co.co_stacksize,
co.co_flags | 0x100, # 0x100 == CO_ITERABLE_COROUTINE
co.co_code,
co.co_consts, co.co_names, co.co_varnames, co.co_filename,
co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars,
co.co_cellvars)
return func
# The following code is primarily to support functions that
# return generator-like objects (for instance generators
# compiled with Cython).
# Delay functools and _collections_abc import for speeding up types import.
import functools
import _collections_abc
@functools.wraps(func)
def wrapped(*args, **kwargs):
coro = func(*args, **kwargs)
if (coro.__class__ is CoroutineType or
coro.__class__ is GeneratorType and coro.gi_code.co_flags & 0x100):
# 'coro' is a native coroutine object or an iterable coroutine
return coro
if (isinstance(coro, _collections_abc.Generator) and
not isinstance(coro, _collections_abc.Coroutine)):
# 'coro' is either a pure Python generator iterator, or it
# implements collections.abc.Generator (and does not implement
# collections.abc.Coroutine).
return _GeneratorWrapper(coro)
# 'coro' is either an instance of collections.abc.Coroutine or
# some other object -- pass it through.
return coro
return wrapped
__all__ = [n for n in globals() if n[:1] != '_']

554
Lib/warnings.py Normal file
View File

@@ -0,0 +1,554 @@
"""Python part of the warnings subsystem."""
import sys
__all__ = ["warn", "warn_explicit", "showwarning",
"formatwarning", "filterwarnings", "simplefilter",
"resetwarnings", "catch_warnings"]
def showwarning(message, category, filename, lineno, file=None, line=None):
"""Hook to write a warning to a file; replace if you like."""
msg = WarningMessage(message, category, filename, lineno, file, line)
_showwarnmsg_impl(msg)
def formatwarning(message, category, filename, lineno, line=None):
"""Function to format a warning the standard way."""
msg = WarningMessage(message, category, filename, lineno, None, line)
return _formatwarnmsg_impl(msg)
def _showwarnmsg_impl(msg):
file = msg.file
if file is None:
file = sys.stderr
if file is None:
# sys.stderr is None when run with pythonw.exe:
# warnings get lost
return
text = _formatwarnmsg(msg)
try:
file.write(text)
except OSError:
# the file (probably stderr) is invalid - this warning gets lost.
pass
def _formatwarnmsg_impl(msg):
s = ("%s:%s: %s: %s\n"
% (msg.filename, msg.lineno, msg.category.__name__,
msg.message))
if msg.line is None:
try:
import linecache
line = linecache.getline(msg.filename, msg.lineno)
except Exception:
# When a warning is logged during Python shutdown, linecache
# and the import machinery don't work anymore
line = None
linecache = None
else:
line = msg.line
if line:
line = line.strip()
s += " %s\n" % line
if msg.source is not None:
try:
import tracemalloc
tb = tracemalloc.get_object_traceback(msg.source)
except Exception:
# When a warning is logged during Python shutdown, tracemalloc
# and the import machinery don't work anymore
tb = None
if tb is not None:
s += 'Object allocated at (most recent call last):\n'
for frame in tb:
s += (' File "%s", lineno %s\n'
% (frame.filename, frame.lineno))
try:
if linecache is not None:
line = linecache.getline(frame.filename, frame.lineno)
else:
line = None
except Exception:
line = None
if line:
line = line.strip()
s += ' %s\n' % line
return s
# Keep a reference to check if the function was replaced
_showwarning_orig = showwarning
def _showwarnmsg(msg):
"""Hook to write a warning to a file; replace if you like."""
try:
sw = showwarning
except NameError:
pass
else:
if sw is not _showwarning_orig:
# warnings.showwarning() was replaced
if not callable(sw):
raise TypeError("warnings.showwarning() must be set to a "
"function or method")
sw(msg.message, msg.category, msg.filename, msg.lineno,
msg.file, msg.line)
return
_showwarnmsg_impl(msg)
# Keep a reference to check if the function was replaced
_formatwarning_orig = formatwarning
def _formatwarnmsg(msg):
"""Function to format a warning the standard way."""
try:
fw = formatwarning
except NameError:
pass
else:
if fw is not _formatwarning_orig:
# warnings.formatwarning() was replaced
return fw(msg.message, msg.category,
msg.filename, msg.lineno, line=msg.line)
return _formatwarnmsg_impl(msg)
def filterwarnings(action, message="", category=Warning, module="", lineno=0,
append=False):
"""Insert an entry into the list of warnings filters (at the front).
'action' -- one of "error", "ignore", "always", "default", "module",
or "once"
'message' -- a regex that the warning message must match
'category' -- a class that the warning must be a subclass of
'module' -- a regex that the module name must match
'lineno' -- an integer line number, 0 matches all warnings
'append' -- if true, append to the list of filters
"""
assert action in ("error", "ignore", "always", "default", "module",
"once"), "invalid action: %r" % (action,)
assert isinstance(message, str), "message must be a string"
assert isinstance(category, type), "category must be a class"
assert issubclass(category, Warning), "category must be a Warning subclass"
assert isinstance(module, str), "module must be a string"
assert isinstance(lineno, int) and lineno >= 0, \
"lineno must be an int >= 0"
if message or module:
import re
if message:
message = re.compile(message, re.I)
else:
message = None
if module:
module = re.compile(module)
else:
module = None
_add_filter(action, message, category, module, lineno, append=append)
def simplefilter(action, category=Warning, lineno=0, append=False):
"""Insert a simple entry into the list of warnings filters (at the front).
A simple filter matches all modules and messages.
'action' -- one of "error", "ignore", "always", "default", "module",
or "once"
'category' -- a class that the warning must be a subclass of
'lineno' -- an integer line number, 0 matches all warnings
'append' -- if true, append to the list of filters
"""
assert action in ("error", "ignore", "always", "default", "module",
"once"), "invalid action: %r" % (action,)
assert isinstance(lineno, int) and lineno >= 0, \
"lineno must be an int >= 0"
_add_filter(action, None, category, None, lineno, append=append)
def _add_filter(*item, append):
# Remove possible duplicate filters, so new one will be placed
# in correct place. If append=True and duplicate exists, do nothing.
if not append:
try:
filters.remove(item)
except ValueError:
pass
filters.insert(0, item)
else:
if item not in filters:
filters.append(item)
_filters_mutated()
def resetwarnings():
"""Clear the list of warning filters, so that no filters are active."""
filters[:] = []
_filters_mutated()
class _OptionError(Exception):
"""Exception used by option processing helpers."""
pass
# Helper to process -W options passed via sys.warnoptions
def _processoptions(args):
for arg in args:
try:
_setoption(arg)
except _OptionError as msg:
print("Invalid -W option ignored:", msg, file=sys.stderr)
# Helper for _processoptions()
def _setoption(arg):
import re
parts = arg.split(':')
if len(parts) > 5:
raise _OptionError("too many fields (max 5): %r" % (arg,))
while len(parts) < 5:
parts.append('')
action, message, category, module, lineno = [s.strip()
for s in parts]
action = _getaction(action)
message = re.escape(message)
category = _getcategory(category)
module = re.escape(module)
if module:
module = module + '$'
if lineno:
try:
lineno = int(lineno)
if lineno < 0:
raise ValueError
except (ValueError, OverflowError):
raise _OptionError("invalid lineno %r" % (lineno,)) from None
else:
lineno = 0
filterwarnings(action, message, category, module, lineno)
# Helper for _setoption()
def _getaction(action):
if not action:
return "default"
if action == "all": return "always" # Alias
for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
if a.startswith(action):
return a
raise _OptionError("invalid action: %r" % (action,))
# Helper for _setoption()
def _getcategory(category):
import re
if not category:
return Warning
if re.match("^[a-zA-Z0-9_]+$", category):
try:
cat = eval(category)
except NameError:
raise _OptionError("unknown warning category: %r" % (category,)) from None
else:
i = category.rfind(".")
module = category[:i]
klass = category[i+1:]
try:
m = __import__(module, None, None, [klass])
except ImportError:
raise _OptionError("invalid module name: %r" % (module,)) from None
try:
cat = getattr(m, klass)
except AttributeError:
raise _OptionError("unknown warning category: %r" % (category,)) from None
if not issubclass(cat, Warning):
raise _OptionError("invalid warning category: %r" % (category,))
return cat
def _is_internal_frame(frame):
"""Signal whether the frame is an internal CPython implementation detail."""
filename = frame.f_code.co_filename
return 'importlib' in filename and '_bootstrap' in filename
def _next_external_frame(frame):
"""Find the next frame that doesn't involve CPython internals."""
frame = frame.f_back
while frame is not None and _is_internal_frame(frame):
frame = frame.f_back
return frame
# Code typically replaced by _warnings
def warn(message, category=None, stacklevel=1, source=None):
"""Issue a warning, or maybe ignore it or raise an exception."""
# Check if message is already a Warning object
if isinstance(message, Warning):
category = message.__class__
# Check category argument
if category is None:
category = UserWarning
if not (isinstance(category, type) and issubclass(category, Warning)):
raise TypeError("category must be a Warning subclass, "
"not '{:s}'".format(type(category).__name__))
# Get context information
try:
if stacklevel <= 1 or _is_internal_frame(sys._getframe(1)):
# If frame is too small to care or if the warning originated in
# internal code, then do not try to hide any frames.
frame = sys._getframe(stacklevel)
else:
frame = sys._getframe(1)
# Look for one frame less since the above line starts us off.
for x in range(stacklevel-1):
frame = _next_external_frame(frame)
if frame is None:
raise ValueError
except ValueError:
globals = sys.__dict__
lineno = 1
else:
globals = frame.f_globals
lineno = frame.f_lineno
if '__name__' in globals:
module = globals['__name__']
else:
module = "<string>"
filename = globals.get('__file__')
if filename:
fnl = filename.lower()
if fnl.endswith(".pyc"):
filename = filename[:-1]
else:
if module == "__main__":
try:
filename = sys.argv[0]
except AttributeError:
# embedded interpreters don't have sys.argv, see bug #839151
filename = '__main__'
if not filename:
filename = module
registry = globals.setdefault("__warningregistry__", {})
warn_explicit(message, category, filename, lineno, module, registry,
globals, source)
def warn_explicit(message, category, filename, lineno,
module=None, registry=None, module_globals=None,
source=None):
lineno = int(lineno)
if module is None:
module = filename or "<unknown>"
if module[-3:].lower() == ".py":
module = module[:-3] # XXX What about leading pathname?
if registry is None:
registry = {}
if registry.get('version', 0) != _filters_version:
registry.clear()
registry['version'] = _filters_version
if isinstance(message, Warning):
text = str(message)
category = message.__class__
else:
text = message
message = category(message)
key = (text, category, lineno)
# Quick test for common case
if registry.get(key):
return
# Search the filters
for item in filters:
action, msg, cat, mod, ln = item
if ((msg is None or msg.match(text)) and
issubclass(category, cat) and
(mod is None or mod.match(module)) and
(ln == 0 or lineno == ln)):
break
else:
action = defaultaction
# Early exit actions
if action == "ignore":
return
# Prime the linecache for formatting, in case the
# "file" is actually in a zipfile or something.
import linecache
linecache.getlines(filename, module_globals)
if action == "error":
raise message
# Other actions
if action == "once":
registry[key] = 1
oncekey = (text, category)
if onceregistry.get(oncekey):
return
onceregistry[oncekey] = 1
elif action == "always":
pass
elif action == "module":
registry[key] = 1
altkey = (text, category, 0)
if registry.get(altkey):
return
registry[altkey] = 1
elif action == "default":
registry[key] = 1
else:
# Unrecognized actions are errors
raise RuntimeError(
"Unrecognized action (%r) in warnings.filters:\n %s" %
(action, item))
# Print message and context
msg = WarningMessage(message, category, filename, lineno, source)
_showwarnmsg(msg)
class WarningMessage(object):
_WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
"line", "source")
def __init__(self, message, category, filename, lineno, file=None,
line=None, source=None):
self.message = message
self.category = category
self.filename = filename
self.lineno = lineno
self.file = file
self.line = line
self.source = source
self._category_name = category.__name__ if category else None
def __str__(self):
return ("{message : %r, category : %r, filename : %r, lineno : %s, "
"line : %r}" % (self.message, self._category_name,
self.filename, self.lineno, self.line))
class catch_warnings(object):
"""A context manager that copies and restores the warnings filter upon
exiting the context.
The 'record' argument specifies whether warnings should be captured by a
custom implementation of warnings.showwarning() and be appended to a list
returned by the context manager. Otherwise None is returned by the context
manager. The objects appended to the list are arguments whose attributes
mirror the arguments to showwarning().
The 'module' argument is to specify an alternative module to the module
named 'warnings' and imported under that name. This argument is only useful
when testing the warnings module itself.
"""
def __init__(self, *, record=False, module=None):
"""Specify whether to record warnings and if an alternative module
should be used other than sys.modules['warnings'].
For compatibility with Python 3.0, please consider all arguments to be
keyword-only.
"""
self._record = record
self._module = sys.modules['warnings'] if module is None else module
self._entered = False
def __repr__(self):
args = []
if self._record:
args.append("record=True")
if self._module is not sys.modules['warnings']:
args.append("module=%r" % self._module)
name = type(self).__name__
return "%s(%s)" % (name, ", ".join(args))
def __enter__(self):
if self._entered:
raise RuntimeError("Cannot enter %r twice" % self)
self._entered = True
self._filters = self._module.filters
self._module.filters = self._filters[:]
self._module._filters_mutated()
self._showwarning = self._module.showwarning
self._showwarnmsg_impl = self._module._showwarnmsg_impl
if self._record:
log = []
self._module._showwarnmsg_impl = log.append
# Reset showwarning() to the default implementation to make sure
# that _showwarnmsg() calls _showwarnmsg_impl()
self._module.showwarning = self._module._showwarning_orig
return log
else:
return None
def __exit__(self, *exc_info):
if not self._entered:
raise RuntimeError("Cannot exit %r without entering first" % self)
self._module.filters = self._filters
self._module._filters_mutated()
self._module.showwarning = self._showwarning
self._module._showwarnmsg_impl = self._showwarnmsg_impl
# Private utility function called by _PyErr_WarnUnawaitedCoroutine
def _warn_unawaited_coroutine(coro):
msg_lines = [
f"coroutine '{coro.__qualname__}' was never awaited\n"
]
if coro.cr_origin is not None:
import linecache, traceback
def extract():
for filename, lineno, funcname in reversed(coro.cr_origin):
line = linecache.getline(filename, lineno)
yield (filename, lineno, funcname, line)
msg_lines.append("Coroutine created at (most recent call last)\n")
msg_lines += traceback.format_list(list(extract()))
msg = "".join(msg_lines).rstrip("\n")
# Passing source= here means that if the user happens to have tracemalloc
# enabled and tracking where the coroutine was created, the warning will
# contain that traceback. This does mean that if they have *both*
# coroutine origin tracking *and* tracemalloc enabled, they'll get two
# partially-redundant tracebacks. If we wanted to be clever we could
# probably detect this case and avoid it, but for now we don't bother.
warn(msg, category=RuntimeWarning, stacklevel=2, source=coro)
# filters contains a sequence of filter 5-tuples
# The components of the 5-tuple are:
# - an action: error, ignore, always, default, module, or once
# - a compiled regex that must match the warning message
# - a class representing the warning category
# - a compiled regex that must match the module that is being warned
# - a line number for the line being warning, or 0 to mean any line
# If either if the compiled regexs are None, match anything.
try:
from _warnings import (filters, _defaultaction, _onceregistry,
warn, warn_explicit, _filters_mutated)
defaultaction = _defaultaction
onceregistry = _onceregistry
_warnings_defaults = True
except ImportError:
filters = []
defaultaction = "default"
onceregistry = {}
_filters_version = 1
def _filters_mutated():
global _filters_version
_filters_version += 1
_warnings_defaults = False
# Module initialization
_processoptions(sys.warnoptions)
if not _warnings_defaults:
# Several warning categories are ignored by default in regular builds
if not hasattr(sys, 'gettotalrefcount'):
filterwarnings("default", category=DeprecationWarning,
module="__main__", append=1)
simplefilter("ignore", category=DeprecationWarning, append=1)
simplefilter("ignore", category=PendingDeprecationWarning, append=1)
simplefilter("ignore", category=ImportWarning, append=1)
simplefilter("ignore", category=ResourceWarning, append=1)
del _warnings_defaults

632
Lib/weakref.py Normal file
View File

@@ -0,0 +1,632 @@
"""Weak reference support for Python.
This module is an implementation of PEP 205:
http://www.python.org/dev/peps/pep-0205/
"""
# Naming convention: Variables named "wr" are weak reference objects;
# they are called this instead of "ref" to avoid name collisions with
# the module-global ref() function imported from _weakref.
from _weakref import (
getweakrefcount,
getweakrefs,
ref,
proxy,
CallableProxyType,
ProxyType,
ReferenceType,
_remove_dead_weakref)
from _weakrefset import WeakSet, _IterationGuard
import _collections_abc # Import after _weakref to avoid circular import.
import sys
import itertools
ProxyTypes = (ProxyType, CallableProxyType)
__all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
"WeakKeyDictionary", "ReferenceType", "ProxyType",
"CallableProxyType", "ProxyTypes", "WeakValueDictionary",
"WeakSet", "WeakMethod", "finalize"]
class WeakMethod(ref):
"""
A custom `weakref.ref` subclass which simulates a weak reference to
a bound method, working around the lifetime problem of bound methods.
"""
__slots__ = "_func_ref", "_meth_type", "_alive", "__weakref__"
def __new__(cls, meth, callback=None):
try:
obj = meth.__self__
func = meth.__func__
except AttributeError:
raise TypeError("argument should be a bound method, not {}"
.format(type(meth))) from None
def _cb(arg):
# The self-weakref trick is needed to avoid creating a reference
# cycle.
self = self_wr()
if self._alive:
self._alive = False
if callback is not None:
callback(self)
self = ref.__new__(cls, obj, _cb)
self._func_ref = ref(func, _cb)
self._meth_type = type(meth)
self._alive = True
self_wr = ref(self)
return self
def __call__(self):
obj = super().__call__()
func = self._func_ref()
if obj is None or func is None:
return None
return self._meth_type(func, obj)
def __eq__(self, other):
if isinstance(other, WeakMethod):
if not self._alive or not other._alive:
return self is other
return ref.__eq__(self, other) and self._func_ref == other._func_ref
return False
def __ne__(self, other):
if isinstance(other, WeakMethod):
if not self._alive or not other._alive:
return self is not other
return ref.__ne__(self, other) or self._func_ref != other._func_ref
return True
__hash__ = ref.__hash__
class WeakValueDictionary(_collections_abc.MutableMapping):
"""Mapping class that references values weakly.
Entries in the dictionary will be discarded when no strong
reference to the value exists anymore
"""
# We inherit the constructor without worrying about the input
# dictionary; since it uses our .update() method, we get the right
# checks (if the other dictionary is a WeakValueDictionary,
# objects are unwrapped on the way out, and we always wrap on the
# way in).
def __init__(*args, **kw):
if not args:
raise TypeError("descriptor '__init__' of 'WeakValueDictionary' "
"object needs an argument")
self, *args = args
if len(args) > 1:
raise TypeError('expected at most 1 arguments, got %d' % len(args))
def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref):
self = selfref()
if self is not None:
if self._iterating:
self._pending_removals.append(wr.key)
else:
# Atomic removal is necessary since this function
# can be called asynchronously by the GC
_atomic_removal(d, wr.key)
self._remove = remove
# A list of keys to be removed
self._pending_removals = []
self._iterating = set()
self.data = d = {}
self.update(*args, **kw)
def _commit_removals(self):
l = self._pending_removals
d = self.data
# We shouldn't encounter any KeyError, because this method should
# always be called *before* mutating the dict.
while l:
key = l.pop()
_remove_dead_weakref(d, key)
def __getitem__(self, key):
if self._pending_removals:
self._commit_removals()
o = self.data[key]()
if o is None:
raise KeyError(key)
else:
return o
def __delitem__(self, key):
if self._pending_removals:
self._commit_removals()
del self.data[key]
def __len__(self):
if self._pending_removals:
self._commit_removals()
return len(self.data)
def __contains__(self, key):
if self._pending_removals:
self._commit_removals()
try:
o = self.data[key]()
except KeyError:
return False
return o is not None
def __repr__(self):
return "<%s at %#x>" % (self.__class__.__name__, id(self))
def __setitem__(self, key, value):
if self._pending_removals:
self._commit_removals()
self.data[key] = KeyedRef(value, self._remove, key)
def copy(self):
if self._pending_removals:
self._commit_removals()
new = WeakValueDictionary()
for key, wr in self.data.items():
o = wr()
if o is not None:
new[key] = o
return new
__copy__ = copy
def __deepcopy__(self, memo):
from copy import deepcopy
if self._pending_removals:
self._commit_removals()
new = self.__class__()
for key, wr in self.data.items():
o = wr()
if o is not None:
new[deepcopy(key, memo)] = o
return new
def get(self, key, default=None):
if self._pending_removals:
self._commit_removals()
try:
wr = self.data[key]
except KeyError:
return default
else:
o = wr()
if o is None:
# This should only happen
return default
else:
return o
def items(self):
if self._pending_removals:
self._commit_removals()
with _IterationGuard(self):
for k, wr in self.data.items():
v = wr()
if v is not None:
yield k, v
def keys(self):
if self._pending_removals:
self._commit_removals()
with _IterationGuard(self):
for k, wr in self.data.items():
if wr() is not None:
yield k
__iter__ = keys
def itervaluerefs(self):
"""Return an iterator that yields the weak references to the values.
The references are not guaranteed to be 'live' at the time
they are used, so the result of calling the references needs
to be checked before being used. This can be used to avoid
creating references that will cause the garbage collector to
keep the values around longer than needed.
"""
if self._pending_removals:
self._commit_removals()
with _IterationGuard(self):
yield from self.data.values()
def values(self):
if self._pending_removals:
self._commit_removals()
with _IterationGuard(self):
for wr in self.data.values():
obj = wr()
if obj is not None:
yield obj
def popitem(self):
if self._pending_removals:
self._commit_removals()
while True:
key, wr = self.data.popitem()
o = wr()
if o is not None:
return key, o
def pop(self, key, *args):
if self._pending_removals:
self._commit_removals()
try:
o = self.data.pop(key)()
except KeyError:
o = None
if o is None:
if args:
return args[0]
else:
raise KeyError(key)
else:
return o
def setdefault(self, key, default=None):
try:
o = self.data[key]()
except KeyError:
o = None
if o is None:
if self._pending_removals:
self._commit_removals()
self.data[key] = KeyedRef(default, self._remove, key)
return default
else:
return o
def update(*args, **kwargs):
if not args:
raise TypeError("descriptor 'update' of 'WeakValueDictionary' "
"object needs an argument")
self, *args = args
if len(args) > 1:
raise TypeError('expected at most 1 arguments, got %d' % len(args))
dict = args[0] if args else None
if self._pending_removals:
self._commit_removals()
d = self.data
if dict is not None:
if not hasattr(dict, "items"):
dict = type({})(dict)
for key, o in dict.items():
d[key] = KeyedRef(o, self._remove, key)
if len(kwargs):
self.update(kwargs)
def valuerefs(self):
"""Return a list of weak references to the values.
The references are not guaranteed to be 'live' at the time
they are used, so the result of calling the references needs
to be checked before being used. This can be used to avoid
creating references that will cause the garbage collector to
keep the values around longer than needed.
"""
if self._pending_removals:
self._commit_removals()
return list(self.data.values())
class KeyedRef(ref):
"""Specialized reference that includes a key corresponding to the value.
This is used in the WeakValueDictionary to avoid having to create
a function object for each key stored in the mapping. A shared
callback object can use the 'key' attribute of a KeyedRef instead
of getting a reference to the key from an enclosing scope.
"""
__slots__ = "key",
def __new__(type, ob, callback, key):
self = ref.__new__(type, ob, callback)
self.key = key
return self
def __init__(self, ob, callback, key):
super().__init__(ob, callback)
class WeakKeyDictionary(_collections_abc.MutableMapping):
""" Mapping class that references keys weakly.
Entries in the dictionary will be discarded when there is no
longer a strong reference to the key. This can be used to
associate additional data with an object owned by other parts of
an application without adding attributes to those objects. This
can be especially useful with objects that override attribute
accesses.
"""
def __init__(self, dict=None):
self.data = {}
def remove(k, selfref=ref(self)):
self = selfref()
if self is not None:
if self._iterating:
self._pending_removals.append(k)
else:
del self.data[k]
self._remove = remove
# A list of dead weakrefs (keys to be removed)
self._pending_removals = []
self._iterating = set()
self._dirty_len = False
if dict is not None:
self.update(dict)
def _commit_removals(self):
# NOTE: We don't need to call this method before mutating the dict,
# because a dead weakref never compares equal to a live weakref,
# even if they happened to refer to equal objects.
# However, it means keys may already have been removed.
l = self._pending_removals
d = self.data
while l:
try:
del d[l.pop()]
except KeyError:
pass
def _scrub_removals(self):
d = self.data
self._pending_removals = [k for k in self._pending_removals if k in d]
self._dirty_len = False
def __delitem__(self, key):
self._dirty_len = True
del self.data[ref(key)]
def __getitem__(self, key):
return self.data[ref(key)]
def __len__(self):
if self._dirty_len and self._pending_removals:
# self._pending_removals may still contain keys which were
# explicitly removed, we have to scrub them (see issue #21173).
self._scrub_removals()
return len(self.data) - len(self._pending_removals)
def __repr__(self):
return "<%s at %#x>" % (self.__class__.__name__, id(self))
def __setitem__(self, key, value):
self.data[ref(key, self._remove)] = value
def copy(self):
new = WeakKeyDictionary()
for key, value in self.data.items():
o = key()
if o is not None:
new[o] = value
return new
__copy__ = copy
def __deepcopy__(self, memo):
from copy import deepcopy
new = self.__class__()
for key, value in self.data.items():
o = key()
if o is not None:
new[o] = deepcopy(value, memo)
return new
def get(self, key, default=None):
return self.data.get(ref(key),default)
def __contains__(self, key):
try:
wr = ref(key)
except TypeError:
return False
return wr in self.data
def items(self):
with _IterationGuard(self):
for wr, value in self.data.items():
key = wr()
if key is not None:
yield key, value
def keys(self):
with _IterationGuard(self):
for wr in self.data:
obj = wr()
if obj is not None:
yield obj
__iter__ = keys
def values(self):
with _IterationGuard(self):
for wr, value in self.data.items():
if wr() is not None:
yield value
def keyrefs(self):
"""Return a list of weak references to the keys.
The references are not guaranteed to be 'live' at the time
they are used, so the result of calling the references needs
to be checked before being used. This can be used to avoid
creating references that will cause the garbage collector to
keep the keys around longer than needed.
"""
return list(self.data)
def popitem(self):
self._dirty_len = True
while True:
key, value = self.data.popitem()
o = key()
if o is not None:
return o, value
def pop(self, key, *args):
self._dirty_len = True
return self.data.pop(ref(key), *args)
def setdefault(self, key, default=None):
return self.data.setdefault(ref(key, self._remove),default)
def update(self, dict=None, **kwargs):
d = self.data
if dict is not None:
if not hasattr(dict, "items"):
dict = type({})(dict)
for key, value in dict.items():
d[ref(key, self._remove)] = value
if len(kwargs):
self.update(kwargs)
class finalize:
"""Class for finalization of weakrefable objects
finalize(obj, func, *args, **kwargs) returns a callable finalizer
object which will be called when obj is garbage collected. The
first time the finalizer is called it evaluates func(*arg, **kwargs)
and returns the result. After this the finalizer is dead, and
calling it just returns None.
When the program exits any remaining finalizers for which the
atexit attribute is true will be run in reverse order of creation.
By default atexit is true.
"""
# Finalizer objects don't have any state of their own. They are
# just used as keys to lookup _Info objects in the registry. This
# ensures that they cannot be part of a ref-cycle.
__slots__ = ()
_registry = {}
_shutdown = False
_index_iter = itertools.count()
_dirty = False
_registered_with_atexit = False
class _Info:
__slots__ = ("weakref", "func", "args", "kwargs", "atexit", "index")
def __init__(self, obj, func, *args, **kwargs):
if not self._registered_with_atexit:
# We may register the exit function more than once because
# of a thread race, but that is harmless
import atexit
atexit.register(self._exitfunc)
finalize._registered_with_atexit = True
info = self._Info()
info.weakref = ref(obj, self)
info.func = func
info.args = args
info.kwargs = kwargs or None
info.atexit = True
info.index = next(self._index_iter)
self._registry[self] = info
finalize._dirty = True
def __call__(self, _=None):
"""If alive then mark as dead and return func(*args, **kwargs);
otherwise return None"""
info = self._registry.pop(self, None)
if info and not self._shutdown:
return info.func(*info.args, **(info.kwargs or {}))
def detach(self):
"""If alive then mark as dead and return (obj, func, args, kwargs);
otherwise return None"""
info = self._registry.get(self)
obj = info and info.weakref()
if obj is not None and self._registry.pop(self, None):
return (obj, info.func, info.args, info.kwargs or {})
def peek(self):
"""If alive then return (obj, func, args, kwargs);
otherwise return None"""
info = self._registry.get(self)
obj = info and info.weakref()
if obj is not None:
return (obj, info.func, info.args, info.kwargs or {})
@property
def alive(self):
"""Whether finalizer is alive"""
return self in self._registry
@property
def atexit(self):
"""Whether finalizer should be called at exit"""
info = self._registry.get(self)
return bool(info) and info.atexit
@atexit.setter
def atexit(self, value):
info = self._registry.get(self)
if info:
info.atexit = bool(value)
def __repr__(self):
info = self._registry.get(self)
obj = info and info.weakref()
if obj is None:
return '<%s object at %#x; dead>' % (type(self).__name__, id(self))
else:
return '<%s object at %#x; for %r at %#x>' % \
(type(self).__name__, id(self), type(obj).__name__, id(obj))
@classmethod
def _select_for_exit(cls):
# Return live finalizers marked for exit, oldest first
L = [(f,i) for (f,i) in cls._registry.items() if i.atexit]
L.sort(key=lambda item:item[1].index)
return [f for (f,i) in L]
@classmethod
def _exitfunc(cls):
# At shutdown invoke finalizers for which atexit is true.
# This is called once all other non-daemonic threads have been
# joined.
reenable_gc = False
try:
if cls._registry:
import gc
if gc.isenabled():
reenable_gc = True
gc.disable()
pending = None
while True:
if pending is None or finalize._dirty:
pending = cls._select_for_exit()
finalize._dirty = False
if not pending:
break
f = pending.pop()
try:
# gc is disabled, so (assuming no daemonic
# threads) the following is the only line in
# this function which might trigger creation
# of a new finalizer
f()
except Exception:
sys.excepthook(*sys.exc_info())
assert f not in cls._registry
finally:
# prevent any more finalizers from executing during shutdown
finalize._shutdown = True
if reenable_gc:
gc.enable()

241
Lib/xdrlib.py Normal file
View File

@@ -0,0 +1,241 @@
"""Implements (a subset of) Sun XDR -- eXternal Data Representation.
See: RFC 1014
"""
import struct
from io import BytesIO
from functools import wraps
__all__ = ["Error", "Packer", "Unpacker", "ConversionError"]
# exceptions
class Error(Exception):
"""Exception class for this module. Use:
except xdrlib.Error as var:
# var has the Error instance for the exception
Public ivars:
msg -- contains the message
"""
def __init__(self, msg):
self.msg = msg
def __repr__(self):
return repr(self.msg)
def __str__(self):
return str(self.msg)
class ConversionError(Error):
pass
def raise_conversion_error(function):
""" Wrap any raised struct.errors in a ConversionError. """
@wraps(function)
def result(self, value):
try:
return function(self, value)
except struct.error as e:
raise ConversionError(e.args[0]) from None
return result
class Packer:
"""Pack various data representations into a buffer."""
def __init__(self):
self.reset()
def reset(self):
self.__buf = BytesIO()
def get_buffer(self):
return self.__buf.getvalue()
# backwards compatibility
get_buf = get_buffer
@raise_conversion_error
def pack_uint(self, x):
self.__buf.write(struct.pack('>L', x))
@raise_conversion_error
def pack_int(self, x):
self.__buf.write(struct.pack('>l', x))
pack_enum = pack_int
def pack_bool(self, x):
if x: self.__buf.write(b'\0\0\0\1')
else: self.__buf.write(b'\0\0\0\0')
def pack_uhyper(self, x):
try:
self.pack_uint(x>>32 & 0xffffffff)
except (TypeError, struct.error) as e:
raise ConversionError(e.args[0]) from None
try:
self.pack_uint(x & 0xffffffff)
except (TypeError, struct.error) as e:
raise ConversionError(e.args[0]) from None
pack_hyper = pack_uhyper
@raise_conversion_error
def pack_float(self, x):
self.__buf.write(struct.pack('>f', x))
@raise_conversion_error
def pack_double(self, x):
self.__buf.write(struct.pack('>d', x))
def pack_fstring(self, n, s):
if n < 0:
raise ValueError('fstring size must be nonnegative')
data = s[:n]
n = ((n+3)//4)*4
data = data + (n - len(data)) * b'\0'
self.__buf.write(data)
pack_fopaque = pack_fstring
def pack_string(self, s):
n = len(s)
self.pack_uint(n)
self.pack_fstring(n, s)
pack_opaque = pack_string
pack_bytes = pack_string
def pack_list(self, list, pack_item):
for item in list:
self.pack_uint(1)
pack_item(item)
self.pack_uint(0)
def pack_farray(self, n, list, pack_item):
if len(list) != n:
raise ValueError('wrong array size')
for item in list:
pack_item(item)
def pack_array(self, list, pack_item):
n = len(list)
self.pack_uint(n)
self.pack_farray(n, list, pack_item)
class Unpacker:
"""Unpacks various data representations from the given buffer."""
def __init__(self, data):
self.reset(data)
def reset(self, data):
self.__buf = data
self.__pos = 0
def get_position(self):
return self.__pos
def set_position(self, position):
self.__pos = position
def get_buffer(self):
return self.__buf
def done(self):
if self.__pos < len(self.__buf):
raise Error('unextracted data remains')
def unpack_uint(self):
i = self.__pos
self.__pos = j = i+4
data = self.__buf[i:j]
if len(data) < 4:
raise EOFError
return struct.unpack('>L', data)[0]
def unpack_int(self):
i = self.__pos
self.__pos = j = i+4
data = self.__buf[i:j]
if len(data) < 4:
raise EOFError
return struct.unpack('>l', data)[0]
unpack_enum = unpack_int
def unpack_bool(self):
return bool(self.unpack_int())
def unpack_uhyper(self):
hi = self.unpack_uint()
lo = self.unpack_uint()
return int(hi)<<32 | lo
def unpack_hyper(self):
x = self.unpack_uhyper()
if x >= 0x8000000000000000:
x = x - 0x10000000000000000
return x
def unpack_float(self):
i = self.__pos
self.__pos = j = i+4
data = self.__buf[i:j]
if len(data) < 4:
raise EOFError
return struct.unpack('>f', data)[0]
def unpack_double(self):
i = self.__pos
self.__pos = j = i+8
data = self.__buf[i:j]
if len(data) < 8:
raise EOFError
return struct.unpack('>d', data)[0]
def unpack_fstring(self, n):
if n < 0:
raise ValueError('fstring size must be nonnegative')
i = self.__pos
j = i + (n+3)//4*4
if j > len(self.__buf):
raise EOFError
self.__pos = j
return self.__buf[i:i+n]
unpack_fopaque = unpack_fstring
def unpack_string(self):
n = self.unpack_uint()
return self.unpack_fstring(n)
unpack_opaque = unpack_string
unpack_bytes = unpack_string
def unpack_list(self, unpack_item):
list = []
while 1:
x = self.unpack_uint()
if x == 0: break
if x != 1:
raise ConversionError('0 or 1 expected, got %r' % (x,))
item = unpack_item()
list.append(item)
return list
def unpack_farray(self, n, unpack_item):
list = []
for i in range(n):
list.append(unpack_item())
return list
def unpack_array(self, unpack_item):
n = self.unpack_uint()
return self.unpack_farray(n, unpack_item)

161
README.md
View File

@@ -1,13 +1,20 @@
<img src="./logo.png" width="125" height="125" align="right" />
# RustPython
A Python-3 (CPython >= 3.5.0) Interpreter written in Rust :snake: :scream: :metal:.
A Python-3 (CPython >= 3.5.0) Interpreter written in Rust :snake: :scream: :metal:.
[![Build Status](https://travis-ci.org/RustPython/RustPython.svg?branch=master)](https://travis-ci.org/RustPython/RustPython)
[![Build Status](https://dev.azure.com/ryan0463/ryan/_apis/build/status/RustPython.RustPython?branchName=master)](https://dev.azure.com/ryan0463/ryan/_build/latest?definitionId=1&branchName=master)
[![codecov](https://codecov.io/gh/RustPython/RustPython/branch/master/graph/badge.svg)](https://codecov.io/gh/RustPython/RustPython)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
[![Contributors](https://img.shields.io/github/contributors/RustPython/RustPython.svg)](https://github.com/RustPython/RustPython/graphs/contributors)
[![Gitter](https://badges.gitter.im/RustPython/Lobby.svg)](https://gitter.im/rustpython/Lobby)
# Usage
### Check out our [online demo](https://rustpython.github.io/demo/) running on WebAssembly.
To test RustPython, do the following:
$ git clone https://github.com/RustPython/RustPython
@@ -22,6 +29,13 @@ Or use the interactive shell:
>>>>> 2+2
4
# Disclaimer
RustPython is in a development phase and should not be used in production or a fault intolerant setting.
Our current build supports only a subset of Python syntax.
Contribution is also more than welcome! See our contribution section for more information on this.
# Goals
@@ -30,35 +44,48 @@ Or use the interactive shell:
# Documentation
Currently the project is in an early phase, and so is the documentation.
Currently along with other areas of the project, documentation is still in an early phase.
You can generate documentation by running:
You can read the [online documentation](https://rustpython.github.io/website/rustpython/index.html) for the latest code on master.
You can also generate documentation locally by running:
```shell
$ cargo doc
$ cargo doc # Including documentation for all dependencies
$ cargo doc --no-deps --all # Excluding all dependencies
```
Documentation HTML files can then be found in the `target/doc` directory.
If you wish to update the online documentation, push directly to the `release` branch (or ask a maintainer to do so). This will trigger a Travis build that updates the documentation and WebAssembly demo page.
# Code organization
- `parser`: python lexing, parsing and ast
- `vm`: python virtual machine
- `parser/src`: python lexing, parsing and ast
- `vm/src`: python virtual machine
- `builtins.rs`: Builtin functions
- `compile.rs`: the python compiler from ast to bytecode
- `obj`: python builtin types
- `src`: using the other subcrates to bring rustpython to life.
- `docs`: documentation (work in progress)
- `py_code_object`: CPython bytecode to rustpython bytecode convertor (work in progress)
- `wasm`: Binary crate and resources for WebAssembly build
- `py_code_object`: CPython bytecode to rustpython bytecode converter (work in progress)
- `wasm`: Binary crate and resources for WebAssembly build
- `tests`: integration test snippets
# Contributing
To start contributing, there are a lot of things that need to be done.
Contributions are more than welcome, and in many cases we are happy to guide contributors through PRs or on gitter.
With that in mind, please note this project is maintained by volunteers, some of the best ways to get started are below:
Most tasks are listed in the [issue tracker](https://github.com/RustPython/RustPython/issues).
Another approach is to checkout the sourcecode: builtin functions and object methods are often the simplest
and easiest way to contribute.
Check issues labeled with `good first issue` if you wish to start coding.
Another approach is to checkout the source code: builtin functions and object methods are often the simplest
and easiest way to contribute.
You can also simply run
`cargo run tests/snippets/todo.py` to assist in finding any
`./whats_left.sh` to assist in finding any
unimplemented method.
# Testing
@@ -68,117 +95,50 @@ To test rustpython, there is a collection of python snippets located in the
```shell
$ cd tests
$ pipenv shell
$ pytest -v
$ pipenv install
$ pipenv run pytest -v
```
There also are some unittests, you can run those will cargo:
There also are some unit tests, you can run those with cargo:
```shell
$ cargo test --all
```
# Using another standard library
# Using a standard library
As of now the standard library is under construction.
As of now the standard library is under construction. You can
use a standard library by setting the RUSTPYTHONPATH environment
variable.
To do this, follow this method:
```shell
$ export RUSTPYTHONPATH=~/GIT/RustPython/Lib
$ cargo run -- -c 'import xdrlib'
```
You can play around
with other standard libraries for python. For example,
the [ouroboros library](https://github.com/pybee/ouroboros).
To do this, follow this method:
```shell
$ cd ~/GIT
$ git clone git@github.com:pybee/ouroboros.git
$ export PYTHONPATH=~/GIT/ouroboros/ouroboros
$ cd RustPython
$ cargo run -- -c 'import statistics'
```
# Compiling to WebAssembly
At this stage RustPython only has preliminary support for web assembly. The instructions here are intended for developers or those wishing to run a toy example.
## Setup
To get started, install [wasm-bingden](https://rustwasm.github.io/wasm-bindgen/whirlwind-tour/basic-usage.html)
and [wasm-webpack](https://rustwasm.github.io/wasm-pack/installer/). You will also need to have `npm` installed.
<!-- Using `rustup` add the compile target `wasm32-unknown-emscripten`. To do so you will need to have [rustup](https://rustup.rs/) installed.
```bash
rustup target add wasm32-unknown-emscripten
```
Next, install `emsdk`:
```bash
curl https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz | tar -zxv
cd emsdk-portable/
./emsdk update
./emsdk install sdk-incoming-64bit
./emsdk activate sdk-incoming-64bit
``` -->
## Build
Move into the `wasm` directory. This contains a custom library crate optimized for wasm build of RustPython.
```bash
cd wasm
```
From here run the build. This can take several minutes depending on the machine.
```
wasm-pack build
```
Upon successful build, cd in the the `/pkg` directory and run:
```
npm link
```
Now move back out into the `/app` directory. The files here have been adapted from [wasm-pack-template](https://github.com/rustwasm/wasm-pack-template).
Finally, run:
```
npm install
```
and you will be able to run the files with:
```
webpack-dev-server
```
Open a browser console and see the output of rustpython_wasm. To verify this, modify the line in `app/index.js`
```js
rp.run_code("print('Hello Python!')\n");
```
To the following:
```js
rp.run_code("assert(False)\n");
```
and you should observe: `Execution failed` in your console output, indicating that the execution of RustPython has failed.
[See this doc](wasm/README.md)
# Code style
The code style used is the default rustfmt codestyle. Please format your code accordingly.
The code style used is the default [rustfmt](https://github.com/rust-lang/rustfmt) codestyle. Please format your code accordingly.
We also use [clippy](https://github.com/rust-lang/rust-clippy) to detect rust code issues.
# Community
Chat with us on [gitter][gitter].
# Code of conduct
Our code of conduct [can be found here](code-of-conduct.md).
# Credit
The initial work was based on [windelbouwman/rspython](https://github.com/windelbouwman/rspython) and [shinglyu/RustPython](https://github.com/shinglyu/RustPython)
@@ -192,4 +152,3 @@ These are some useful links to related projects:
- https://github.com/ProgVal/pythonvm-rust
- https://github.com/shinglyu/RustPython
- https://github.com/windelbouwman/rspython

56
azure-pipelines.yml Normal file
View File

@@ -0,0 +1,56 @@
trigger:
- master
jobs:
- job: 'Test'
pool:
vmImage: 'vs2017-win2016'
strategy:
matrix:
Python36:
python.version: '3.6'
maxParallel: 10
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '$(python.version)'
architecture: 'x64'
- script: |
"C:\Program Files\Git\mingw64\bin\curl.exe" -sSf -o rustup-init.exe https://win.rustup.rs/
.\rustup-init.exe -y
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
rustc -V
cargo -V
displayName: 'Installing Rust'
- script: |
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
cargo build --verbose --all
displayName: 'Build'
- script: |
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
cargo test --verbose --all
displayName: 'Run tests'
- script: |
pip install pipenv
pushd tests
pipenv install
popd
displayName: 'Install pipenv and python packages'
- script: |
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
cargo build --verbose --release
displayName: 'Build release'
- script: |
set PATH=%PATH%;%USERPROFILE%\.cargo\bin
pushd tests
pipenv run pytest
popd
displayName: 'Run snippet tests'

19
benchmarks/README.md Normal file
View File

@@ -0,0 +1,19 @@
# Benchmarking
These are some files to determine performance of rustpython.
# Usage
Install pytest and pytest-benchmark:
$ pip install pytest-benchmark
Then run:
$ pytest
# Benchmark source
- https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/nbody-python3-2.html

125
benchmarks/bench.rs Normal file
View File

@@ -0,0 +1,125 @@
#![feature(test)]
extern crate cpython;
extern crate rustpython_parser;
extern crate rustpython_vm;
extern crate test;
use rustpython_vm::pyobject::PyResult;
use rustpython_vm::{compile, VirtualMachine};
#[bench]
fn bench_tokenization(b: &mut test::Bencher) {
use rustpython_parser::lexer::{make_tokenizer, Tok};
let source = include_str!("./benchmarks/minidom.py");
b.bytes = source.len() as _;
b.iter(|| {
let lexer = make_tokenizer(source);
for res in lexer {
let _token: Tok = res.unwrap().1;
}
})
}
#[bench]
fn bench_rustpy_parse_to_ast(b: &mut test::Bencher) {
use rustpython_parser::parser::parse_program;
let source = include_str!("./benchmarks/minidom.py");
b.bytes = source.len() as _;
b.iter(|| parse_program(source).unwrap())
}
#[bench]
fn bench_cpython_parse_to_ast(b: &mut test::Bencher) {
let source = include_str!("./benchmarks/minidom.py");
let gil = cpython::Python::acquire_gil();
let python = gil.python();
let globals = None;
let locals = cpython::PyDict::new(python);
locals.set_item(python, "SOURCE_CODE", source).unwrap();
let code = "compile(SOURCE_CODE, mode=\"exec\", filename=\"minidom.py\")";
b.bytes = source.len() as _;
b.iter(|| {
let res: cpython::PyResult<cpython::PyObject> = python.eval(code, globals, Some(&locals));
assert!(res.is_ok());
})
}
#[bench]
fn bench_cpython_nbody(b: &mut test::Bencher) {
let source = include_str!("./benchmarks/nbody.py");
let gil = cpython::Python::acquire_gil();
let python = gil.python();
let globals = None;
let locals = None;
b.iter(|| {
let res: cpython::PyResult<()> = python.run(source, globals, locals);
assert!(res.is_ok());
})
}
#[bench]
fn bench_cpython_mandelbrot(b: &mut test::Bencher) {
let source = include_str!("./benchmarks/mandelbrot.py");
let gil = cpython::Python::acquire_gil();
let python = gil.python();
let globals = None;
let locals = None;
b.iter(|| {
let res: cpython::PyResult<()> = python.run(source, globals, locals);
assert!(res.is_ok());
})
}
#[bench]
fn bench_rustpy_nbody(b: &mut test::Bencher) {
// NOTE: Take long time.
let source = include_str!("./benchmarks/nbody.py");
let vm = VirtualMachine::new();
let code = match vm.compile(source, &compile::Mode::Single, "<stdin>".to_string()) {
Ok(code) => code,
Err(e) => panic!("{:?}", e),
};
b.iter(|| {
let scope = vm.new_scope_with_builtins();
let res: PyResult = vm.run_code_obj(code.clone(), scope);
assert!(res.is_ok());
})
}
#[bench]
fn bench_rustpy_mandelbrot(b: &mut test::Bencher) {
// NOTE: Take long time.
let source = include_str!("./benchmarks/mandelbrot.py");
let vm = VirtualMachine::new();
let code = match vm.compile(source, &compile::Mode::Single, "<stdin>".to_string()) {
Ok(code) => code,
Err(e) => panic!("{:?}", e),
};
b.iter(|| {
let scope = vm.new_scope_with_builtins();
let res: PyResult = vm.run_code_obj(code.clone(), scope);
assert!(res.is_ok());
})
}

View File

@@ -0,0 +1,33 @@
#!/usr/bin/env python3
# coding: utf-8
w = 50.0
h = 50.0
y = 0.0
while y < h:
x = 0.0
while x < w:
Zr, Zi, Tr, Ti = 0.0, 0.0, 0.0, 0.0
Cr = 2*x/w - 1.5
Ci = 2*y/h - 1.0
i = 0
while i < 50 and Tr+Ti <= 4:
Zi = 2*Zr*Zi + Ci
Zr = Tr - Ti + Cr
Tr = Zr * Zr
Ti = Zi * Zi
i = i+1
if Tr+Ti <= 4:
# print('*', end='')
pass
else:
# print('·', end='')
pass
x = x+1
# print()
y = y+1

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,110 @@
# The Computer Language Benchmarks Game
# https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
#
# originally by Kevin Carson
# modified by Tupteq, Fredrik Johansson, and Daniel Nanz
# modified by Maciej Fijalkowski
# 2to3
# modified by Andriy Misyura
from math import sqrt
def combinations(l):
result = []
for x in range(len(l) - 1):
ls = l[x+1:]
for y in ls:
result.append((l[x][0],l[x][1],l[x][2],y[0],y[1],y[2]))
return result
PI = 3.14159265358979323
SOLAR_MASS = 4 * PI * PI
DAYS_PER_YEAR = 365.24
BODIES = {
'sun': ([0.0, 0.0, 0.0], [0.0, 0.0, 0.0], SOLAR_MASS),
'jupiter': ([4.84143144246472090e+00,
-1.16032004402742839e+00,
-1.03622044471123109e-01],
[1.66007664274403694e-03 * DAYS_PER_YEAR,
7.69901118419740425e-03 * DAYS_PER_YEAR,
-6.90460016972063023e-05 * DAYS_PER_YEAR],
9.54791938424326609e-04 * SOLAR_MASS),
'saturn': ([8.34336671824457987e+00,
4.12479856412430479e+00,
-4.03523417114321381e-01],
[-2.76742510726862411e-03 * DAYS_PER_YEAR,
4.99852801234917238e-03 * DAYS_PER_YEAR,
2.30417297573763929e-05 * DAYS_PER_YEAR],
2.85885980666130812e-04 * SOLAR_MASS),
'uranus': ([1.28943695621391310e+01,
-1.51111514016986312e+01,
-2.23307578892655734e-01],
[2.96460137564761618e-03 * DAYS_PER_YEAR,
2.37847173959480950e-03 * DAYS_PER_YEAR,
-2.96589568540237556e-05 * DAYS_PER_YEAR],
4.36624404335156298e-05 * SOLAR_MASS),
'neptune': ([1.53796971148509165e+01,
-2.59193146099879641e+01,
1.79258772950371181e-01],
[2.68067772490389322e-03 * DAYS_PER_YEAR,
1.62824170038242295e-03 * DAYS_PER_YEAR,
-9.51592254519715870e-05 * DAYS_PER_YEAR],
5.15138902046611451e-05 * SOLAR_MASS) }
SYSTEM = tuple(BODIES.values())
PAIRS = tuple(combinations(SYSTEM))
def advance(dt, n, bodies=SYSTEM, pairs=PAIRS):
for i in range(n):
for ([x1, y1, z1], v1, m1, [x2, y2, z2], v2, m2) in pairs:
dx = x1 - x2
dy = y1 - y2
dz = z1 - z2
dist = sqrt(dx * dx + dy * dy + dz * dz);
mag = dt / (dist*dist*dist)
b1m = m1 * mag
b2m = m2 * mag
v1[0] -= dx * b2m
v1[1] -= dy * b2m
v1[2] -= dz * b2m
v2[2] += dz * b1m
v2[1] += dy * b1m
v2[0] += dx * b1m
for (r, [vx, vy, vz], m) in bodies:
r[0] += dt * vx
r[1] += dt * vy
r[2] += dt * vz
def report_energy(bodies=SYSTEM, pairs=PAIRS, e=0.0):
for ((x1, y1, z1), v1, m1, (x2, y2, z2), v2, m2) in pairs:
dx = x1 - x2
dy = y1 - y2
dz = z1 - z2
e -= (m1 * m2) / ((dx * dx + dy * dy + dz * dz) ** 0.5)
for (r, [vx, vy, vz], m) in bodies:
e += m * (vx * vx + vy * vy + vz * vz) / 2.
# print(f"{e}")
def offset_momentum(ref, bodies=SYSTEM, px=0.0, py=0.0, pz=0.0):
for (r, [vx, vy, vz], m) in bodies:
px -= vx * m
py -= vy * m
pz -= vz * m
(r, v, m) = ref
v[0] = px / m
v[1] = py / m
v[2] = pz / m
def main(n, ref='sun'):
offset_momentum(BODIES[ref])
report_energy()
advance(0.01, n)
report_energy()
main(500)

View File

@@ -0,0 +1,31 @@
import time
import sys
import pytest
import subprocess
from benchmarks import nbody
# Interpreters:
rustpython_exe = '../target/release/rustpython'
cpython_exe = sys.executable
pythons = [
cpython_exe,
rustpython_exe
]
# Benchmark scripts:
benchmarks = [
['benchmarks/nbody.py'],
['benchmarks/mandelbrot.py'],
]
@pytest.mark.parametrize('exe', pythons)
@pytest.mark.parametrize('args', benchmarks)
def test_bench(exe, args, benchmark):
def bench():
subprocess.run([exe] + args)
benchmark(bench)

15
bytecode/Cargo.toml Normal file
View File

@@ -0,0 +1,15 @@
[package]
name = "rustpython-bytecode"
description = "RustPython specific bytecode."
version = "0.1.0"
authors = ["RustPython Team"]
edition = "2018"
repository = "https://github.com/RustPython/RustPython"
license = "MIT"
[dependencies]
bitflags = "1.1"
num-bigint = { version = "0.2", features = ["serde"] }
num-complex = { version = "0.2", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }

469
bytecode/src/bytecode.rs Normal file
View File

@@ -0,0 +1,469 @@
//! Implement python as a virtual machine with bytecodes. This module
//! implements bytecode structure.
use bitflags::bitflags;
use num_bigint::BigInt;
use num_complex::Complex64;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use std::fmt;
/// Sourcode location.
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct Location {
row: usize,
column: usize,
}
impl Location {
pub fn new(row: usize, column: usize) -> Self {
Location { row, column }
}
pub fn row(&self) -> usize {
self.row
}
pub fn column(&self) -> usize {
self.column
}
}
/// Primary container of a single code object. Each python function has
/// a codeobject. Also a module has a codeobject.
#[derive(Clone, PartialEq, Serialize, Deserialize)]
pub struct CodeObject {
pub instructions: Vec<Instruction>,
/// Jump targets.
pub label_map: HashMap<Label, usize>,
pub locations: Vec<Location>,
pub arg_names: Vec<String>, // Names of positional arguments
pub varargs: Varargs, // *args or *
pub kwonlyarg_names: Vec<String>,
pub varkeywords: Varargs, // **kwargs or **
pub source_path: String,
pub first_line_number: usize,
pub obj_name: String, // Name of the object that created this code object
pub is_generator: bool,
}
bitflags! {
#[derive(Serialize, Deserialize)]
pub struct FunctionOpArg: u8 {
const HAS_DEFAULTS = 0x01;
const HAS_KW_ONLY_DEFAULTS = 0x02;
const HAS_ANNOTATIONS = 0x04;
}
}
pub type Label = usize;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum NameScope {
Local,
NonLocal,
Global,
}
/// Transforms a value prior to formatting it.
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ConversionFlag {
/// Converts by calling `str(<value>)`.
Str,
/// Converts by calling `ascii(<value>)`.
Ascii,
/// Converts by calling `repr(<value>)`.
Repr,
}
/// A Single bytecode instruction.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Instruction {
Import {
name: String,
symbols: Vec<String>,
level: usize,
},
ImportStar {
name: String,
level: usize,
},
LoadName {
name: String,
scope: NameScope,
},
StoreName {
name: String,
scope: NameScope,
},
DeleteName {
name: String,
},
StoreSubscript,
DeleteSubscript,
StoreAttr {
name: String,
},
DeleteAttr {
name: String,
},
LoadConst {
value: Constant,
},
UnaryOperation {
op: UnaryOperator,
},
BinaryOperation {
op: BinaryOperator,
inplace: bool,
},
LoadAttr {
name: String,
},
CompareOperation {
op: ComparisonOperator,
},
Pop,
Rotate {
amount: usize,
},
Duplicate,
GetIter,
Pass,
Continue,
Break,
Jump {
target: Label,
},
JumpIf {
target: Label,
},
JumpIfFalse {
target: Label,
},
MakeFunction {
flags: FunctionOpArg,
},
CallFunction {
typ: CallType,
},
ForIter {
target: Label,
},
ReturnValue,
YieldValue,
YieldFrom,
SetupLoop {
start: Label,
end: Label,
},
SetupExcept {
handler: Label,
},
SetupWith {
end: Label,
},
CleanupWith {
end: Label,
},
PopBlock,
Raise {
argc: usize,
},
BuildString {
size: usize,
},
BuildTuple {
size: usize,
unpack: bool,
},
BuildList {
size: usize,
unpack: bool,
},
BuildSet {
size: usize,
unpack: bool,
},
BuildMap {
size: usize,
unpack: bool,
},
BuildSlice {
size: usize,
},
ListAppend {
i: usize,
},
SetAdd {
i: usize,
},
MapAdd {
i: usize,
},
PrintExpr,
LoadBuildClass,
UnpackSequence {
size: usize,
},
UnpackEx {
before: usize,
after: usize,
},
Unpack,
FormatValue {
conversion: Option<ConversionFlag>,
spec: String,
},
PopException,
}
use self::Instruction::*;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum CallType {
Positional(usize),
Keyword(usize),
Ex(bool),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Constant {
Integer { value: BigInt },
Float { value: f64 },
Complex { value: Complex64 },
Boolean { value: bool },
String { value: String },
Bytes { value: Vec<u8> },
Code { code: Box<CodeObject> },
Tuple { elements: Vec<Constant> },
None,
Ellipsis,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ComparisonOperator {
Greater,
GreaterOrEqual,
Less,
LessOrEqual,
Equal,
NotEqual,
In,
NotIn,
Is,
IsNot,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum BinaryOperator {
Power,
Multiply,
MatrixMultiply,
Divide,
FloorDivide,
Modulo,
Add,
Subtract,
Subscript,
Lshift,
Rshift,
And,
Xor,
Or,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum UnaryOperator {
Not,
Invert,
Minus,
Plus,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Varargs {
None,
Unnamed,
Named(String),
}
/*
Maintain a stack of blocks on the VM.
pub enum BlockType {
Loop,
Except,
}
*/
impl CodeObject {
pub fn new(
arg_names: Vec<String>,
varargs: Varargs,
kwonlyarg_names: Vec<String>,
varkeywords: Varargs,
source_path: String,
first_line_number: usize,
obj_name: String,
) -> CodeObject {
CodeObject {
instructions: Vec::new(),
label_map: HashMap::new(),
locations: Vec::new(),
arg_names,
varargs,
kwonlyarg_names,
varkeywords,
source_path,
first_line_number,
obj_name,
is_generator: false,
}
}
pub fn get_constants(&self) -> impl Iterator<Item = &Constant> {
self.instructions.iter().filter_map(|x| {
if let Instruction::LoadConst { value } = x {
Some(value)
} else {
None
}
})
}
}
impl fmt::Display for CodeObject {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let label_targets: HashSet<&usize> = self.label_map.values().collect();
for (offset, instruction) in self.instructions.iter().enumerate() {
let arrow = if label_targets.contains(&offset) {
">>"
} else {
" "
};
write!(f, " {} {:5} ", arrow, offset)?;
instruction.fmt_dis(f, &self.label_map)?;
}
Ok(())
}
}
impl Instruction {
fn fmt_dis(&self, f: &mut fmt::Formatter, label_map: &HashMap<Label, usize>) -> fmt::Result {
macro_rules! w {
($variant:ident) => {
write!(f, "{:20}\n", stringify!($variant))
};
($variant:ident, $var:expr) => {
write!(f, "{:20} ({})\n", stringify!($variant), $var)
};
($variant:ident, $var1:expr, $var2:expr) => {
write!(f, "{:20} ({}, {})\n", stringify!($variant), $var1, $var2)
};
($variant:ident, $var1:expr, $var2:expr, $var3:expr) => {
write!(
f,
"{:20} ({}, {}, {})\n",
stringify!($variant),
$var1,
$var2,
$var3
)
};
}
match self {
Import {
name,
symbols,
level,
} => w!(Import, name, format!("{:?}", symbols), level),
ImportStar { name, level } => w!(ImportStar, name, level),
LoadName { name, scope } => w!(LoadName, name, format!("{:?}", scope)),
StoreName { name, scope } => w!(StoreName, name, format!("{:?}", scope)),
DeleteName { name } => w!(DeleteName, name),
StoreSubscript => w!(StoreSubscript),
DeleteSubscript => w!(DeleteSubscript),
StoreAttr { name } => w!(StoreAttr, name),
DeleteAttr { name } => w!(DeleteAttr, name),
LoadConst { value } => w!(LoadConst, value),
UnaryOperation { op } => w!(UnaryOperation, format!("{:?}", op)),
BinaryOperation { op, inplace } => w!(BinaryOperation, format!("{:?}", op), inplace),
LoadAttr { name } => w!(LoadAttr, name),
CompareOperation { op } => w!(CompareOperation, format!("{:?}", op)),
Pop => w!(Pop),
Rotate { amount } => w!(Rotate, amount),
Duplicate => w!(Duplicate),
GetIter => w!(GetIter),
Pass => w!(Pass),
Continue => w!(Continue),
Break => w!(Break),
Jump { target } => w!(Jump, label_map[target]),
JumpIf { target } => w!(JumpIf, label_map[target]),
JumpIfFalse { target } => w!(JumpIfFalse, label_map[target]),
MakeFunction { flags } => w!(MakeFunction, format!("{:?}", flags)),
CallFunction { typ } => w!(CallFunction, format!("{:?}", typ)),
ForIter { target } => w!(ForIter, label_map[target]),
ReturnValue => w!(ReturnValue),
YieldValue => w!(YieldValue),
YieldFrom => w!(YieldFrom),
SetupLoop { start, end } => w!(SetupLoop, label_map[start], label_map[end]),
SetupExcept { handler } => w!(SetupExcept, handler),
SetupWith { end } => w!(SetupWith, end),
CleanupWith { end } => w!(CleanupWith, end),
PopBlock => w!(PopBlock),
Raise { argc } => w!(Raise, argc),
BuildString { size } => w!(BuildString, size),
BuildTuple { size, unpack } => w!(BuildTuple, size, unpack),
BuildList { size, unpack } => w!(BuildList, size, unpack),
BuildSet { size, unpack } => w!(BuildSet, size, unpack),
BuildMap { size, unpack } => w!(BuildMap, size, unpack),
BuildSlice { size } => w!(BuildSlice, size),
ListAppend { i } => w!(ListAppend, i),
SetAdd { i } => w!(SetAdd, i),
MapAdd { i } => w!(MapAdd, i),
PrintExpr => w!(PrintExpr),
LoadBuildClass => w!(LoadBuildClass),
UnpackSequence { size } => w!(UnpackSequence, size),
UnpackEx { before, after } => w!(UnpackEx, before, after),
Unpack => w!(Unpack),
FormatValue { spec, .. } => w!(FormatValue, spec), // TODO: write conversion
PopException => w!(PopException),
}
}
}
impl fmt::Display for Constant {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Constant::Integer { value } => write!(f, "{}", value),
Constant::Float { value } => write!(f, "{}", value),
Constant::Complex { value } => write!(f, "{}", value),
Constant::Boolean { value } => write!(f, "{}", value),
Constant::String { value } => write!(f, "{:?}", value),
Constant::Bytes { value } => write!(f, "{:?}", value),
Constant::Code { code } => write!(f, "{:?}", code),
Constant::Tuple { elements } => write!(
f,
"({})",
elements
.iter()
.map(|e| format!("{}", e))
.collect::<Vec<_>>()
.join(", ")
),
Constant::None => write!(f, "None"),
Constant::Ellipsis => write!(f, "Ellipsis"),
}
}
}
impl fmt::Debug for CodeObject {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"<code object {} at ??? file {:?}, line {}>",
self.obj_name, self.source_path, self.first_line_number
)
}
}

1
bytecode/src/lib.rs Normal file
View File

@@ -0,0 +1 @@
pub mod bytecode;

77
code-of-conduct.md Normal file
View File

@@ -0,0 +1,77 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at windel.bouwman@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

14
compiler/Cargo.toml Normal file
View File

@@ -0,0 +1,14 @@
[package]
name = "rustpython-compiler"
version = "0.1.0"
description = "Compiler for python code into bytecode for the rustpython VM."
authors = ["RustPython Team"]
repository = "https://github.com/RustPython/RustPython"
license = "MIT"
edition = "2018"
[dependencies]
rustpython-bytecode = { path = "../bytecode", version = "0.1.0" }
rustpython-parser = { path = "../parser", version = "0.1.0" }
num-complex = { version = "0.2", features = ["serde"] }
log = "0.3"

File diff suppressed because it is too large Load Diff

67
compiler/src/error.rs Normal file
View File

@@ -0,0 +1,67 @@
use rustpython_parser::error::{ParseError, ParseErrorType};
use rustpython_parser::lexer::Location;
use std::error::Error;
use std::fmt;
#[derive(Debug)]
pub struct CompileError {
pub error: CompileErrorType,
pub location: Location,
}
impl From<ParseError> for CompileError {
fn from(error: ParseError) -> Self {
CompileError {
error: CompileErrorType::Parse(error.error),
location: error.location,
}
}
}
#[derive(Debug)]
pub enum CompileErrorType {
/// Invalid assignment, cannot store value in target.
Assign(&'static str),
/// Invalid delete
Delete(&'static str),
/// Expected an expression got a statement
ExpectExpr,
/// Parser error
Parse(ParseErrorType),
SyntaxError(String),
/// Multiple `*` detected
StarArgs,
/// Break statement outside of loop.
InvalidBreak,
/// Continue statement outside of loop.
InvalidContinue,
InvalidReturn,
InvalidYield,
}
impl fmt::Display for CompileError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self.error {
CompileErrorType::Assign(target) => write!(f, "can't assign to {}", target),
CompileErrorType::Delete(target) => write!(f, "can't delete {}", target),
CompileErrorType::ExpectExpr => write!(f, "Expecting expression, got statement"),
CompileErrorType::Parse(err) => write!(f, "{}", err),
CompileErrorType::SyntaxError(err) => write!(f, "{}", err),
CompileErrorType::StarArgs => write!(f, "Two starred expressions in assignment"),
CompileErrorType::InvalidBreak => write!(f, "'break' outside loop"),
CompileErrorType::InvalidContinue => write!(f, "'continue' outside loop"),
CompileErrorType::InvalidReturn => write!(f, "'return' outside function"),
CompileErrorType::InvalidYield => write!(f, "'yield' outside function"),
}?;
// Print line number:
write!(f, " at {}", self.location)
}
}
impl Error for CompileError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}
}

9
compiler/src/lib.rs Normal file
View File

@@ -0,0 +1,9 @@
//! Compile a Python AST or source code into bytecode consumable by RustPython or
//! (eventually) CPython.
#[macro_use]
extern crate log;
pub mod compile;
pub mod error;
mod symboltable;

596
compiler/src/symboltable.rs Normal file
View File

@@ -0,0 +1,596 @@
/* Python code is pre-scanned for symbols in the ast.
This ensures that global and nonlocal keywords are picked up.
Then the compiler can use the symbol table to generate proper
load and store instructions for names.
Inspirational file: https://github.com/python/cpython/blob/master/Python/symtable.c
*/
use crate::error::{CompileError, CompileErrorType};
use rustpython_parser::ast;
use rustpython_parser::lexer::Location;
use std::collections::HashMap;
pub fn make_symbol_table(program: &ast::Program) -> Result<SymbolScope, SymbolTableError> {
let mut builder = SymbolTableBuilder::new();
builder.enter_scope();
builder.scan_program(program)?;
assert_eq!(builder.scopes.len(), 1);
let symbol_table = builder.scopes.pop().unwrap();
analyze_symbol_table(&symbol_table, None)?;
Ok(symbol_table)
}
pub fn statements_to_symbol_table(
statements: &[ast::LocatedStatement],
) -> Result<SymbolScope, SymbolTableError> {
let mut builder = SymbolTableBuilder::new();
builder.enter_scope();
builder.scan_statements(statements)?;
assert_eq!(builder.scopes.len(), 1);
let symbol_table = builder.scopes.pop().unwrap();
analyze_symbol_table(&symbol_table, None)?;
Ok(symbol_table)
}
#[derive(Debug)]
pub enum SymbolRole {
Global,
Nonlocal,
Used,
Assigned,
}
/// Captures all symbols in the current scope, and has a list of subscopes in this scope.
pub struct SymbolScope {
/// A set of symbols present on this scope level.
pub symbols: HashMap<String, SymbolRole>,
/// A list of subscopes in the order as found in the
/// AST nodes.
pub sub_scopes: Vec<SymbolScope>,
}
#[derive(Debug)]
pub struct SymbolTableError {
error: String,
location: Location,
}
impl From<SymbolTableError> for CompileError {
fn from(error: SymbolTableError) -> Self {
CompileError {
error: CompileErrorType::SyntaxError(error.error),
location: error.location,
}
}
}
type SymbolTableResult = Result<(), SymbolTableError>;
impl SymbolScope {
pub fn new() -> Self {
SymbolScope {
symbols: HashMap::new(),
sub_scopes: vec![],
}
}
pub fn lookup(&self, name: &str) -> Option<&SymbolRole> {
self.symbols.get(name)
}
}
impl std::fmt::Debug for SymbolScope {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"SymbolScope({:?} symbols, {:?} sub scopes)",
self.symbols.len(),
self.sub_scopes.len()
)
}
}
/* Perform some sort of analysis on nonlocals, globals etc..
See also: https://github.com/python/cpython/blob/master/Python/symtable.c#L410
*/
fn analyze_symbol_table(
symbol_scope: &SymbolScope,
parent_symbol_scope: Option<&SymbolScope>,
) -> SymbolTableResult {
// Analyze sub scopes:
for sub_scope in &symbol_scope.sub_scopes {
analyze_symbol_table(&sub_scope, Some(symbol_scope))?;
}
// Analyze symbols:
for (symbol_name, symbol_role) in &symbol_scope.symbols {
analyze_symbol(symbol_name, symbol_role, parent_symbol_scope)?;
}
Ok(())
}
#[allow(clippy::single_match)]
fn analyze_symbol(
symbol_name: &str,
symbol_role: &SymbolRole,
parent_symbol_scope: Option<&SymbolScope>,
) -> SymbolTableResult {
match symbol_role {
SymbolRole::Nonlocal => {
// check if name is defined in parent scope!
if let Some(parent_symbol_scope) = parent_symbol_scope {
if !parent_symbol_scope.symbols.contains_key(symbol_name) {
return Err(SymbolTableError {
error: format!("no binding for nonlocal '{}' found", symbol_name),
location: Default::default(),
});
}
} else {
return Err(SymbolTableError {
error: format!(
"nonlocal {} defined at place without an enclosing scope",
symbol_name
),
location: Default::default(),
});
}
}
// TODO: add more checks for globals
_ => {}
}
Ok(())
}
pub struct SymbolTableBuilder {
// Scope stack.
pub scopes: Vec<SymbolScope>,
}
impl SymbolTableBuilder {
pub fn new() -> Self {
SymbolTableBuilder { scopes: vec![] }
}
pub fn enter_scope(&mut self) {
let scope = SymbolScope::new();
self.scopes.push(scope);
}
fn leave_scope(&mut self) {
// Pop scope and add to subscopes of parent scope.
let scope = self.scopes.pop().unwrap();
self.scopes.last_mut().unwrap().sub_scopes.push(scope);
}
pub fn scan_program(&mut self, program: &ast::Program) -> SymbolTableResult {
self.scan_statements(&program.statements)?;
Ok(())
}
pub fn scan_statements(&mut self, statements: &[ast::LocatedStatement]) -> SymbolTableResult {
for statement in statements {
self.scan_statement(statement)?;
}
Ok(())
}
fn scan_parameters(&mut self, parameters: &[ast::Parameter]) -> SymbolTableResult {
for parameter in parameters {
self.scan_parameter(parameter)?;
}
Ok(())
}
fn scan_parameter(&mut self, parameter: &ast::Parameter) -> SymbolTableResult {
self.register_name(&parameter.arg, SymbolRole::Assigned)
}
fn scan_parameters_annotations(&mut self, parameters: &[ast::Parameter]) -> SymbolTableResult {
for parameter in parameters {
self.scan_parameter_annotation(parameter)?;
}
Ok(())
}
fn scan_parameter_annotation(&mut self, parameter: &ast::Parameter) -> SymbolTableResult {
if let Some(annotation) = &parameter.annotation {
self.scan_expression(&annotation)?;
}
Ok(())
}
fn scan_statement(&mut self, statement: &ast::LocatedStatement) -> SymbolTableResult {
match &statement.node {
ast::Statement::Global { names } => {
for name in names {
self.register_name(name, SymbolRole::Global)?;
}
}
ast::Statement::Nonlocal { names } => {
for name in names {
self.register_name(name, SymbolRole::Nonlocal)?;
}
}
ast::Statement::FunctionDef {
name,
body,
args,
decorator_list,
returns,
}
| ast::Statement::AsyncFunctionDef {
name,
body,
args,
decorator_list,
returns,
} => {
self.scan_expressions(decorator_list)?;
self.register_name(name, SymbolRole::Assigned)?;
self.enter_function(args)?;
self.scan_statements(body)?;
if let Some(expression) = returns {
self.scan_expression(expression)?;
}
self.leave_scope();
}
ast::Statement::ClassDef {
name,
body,
bases,
keywords,
decorator_list,
} => {
self.register_name(name, SymbolRole::Assigned)?;
self.enter_scope();
self.scan_statements(body)?;
self.leave_scope();
self.scan_expressions(bases)?;
for keyword in keywords {
self.scan_expression(&keyword.value)?;
}
self.scan_expressions(decorator_list)?;
}
ast::Statement::Expression { expression } => self.scan_expression(expression)?,
ast::Statement::If { test, body, orelse } => {
self.scan_expression(test)?;
self.scan_statements(body)?;
if let Some(code) = orelse {
self.scan_statements(code)?;
}
}
ast::Statement::For {
target,
iter,
body,
orelse,
}
| ast::Statement::AsyncFor {
target,
iter,
body,
orelse,
} => {
self.scan_expression(target)?;
self.scan_expression(iter)?;
self.scan_statements(body)?;
if let Some(code) = orelse {
self.scan_statements(code)?;
}
}
ast::Statement::While { test, body, orelse } => {
self.scan_expression(test)?;
self.scan_statements(body)?;
if let Some(code) = orelse {
self.scan_statements(code)?;
}
}
ast::Statement::Break | ast::Statement::Continue | ast::Statement::Pass => {
// No symbols here.
}
ast::Statement::Import { import_parts } => {
for part in import_parts {
if let Some(alias) = &part.alias {
// `import mymodule as myalias`
self.register_name(alias, SymbolRole::Assigned)?;
} else {
if part.symbols.is_empty() {
// `import module`
self.register_name(&part.module, SymbolRole::Assigned)?;
} else {
// `from mymodule import myimport`
for symbol in &part.symbols {
if let Some(alias) = &symbol.alias {
// `from mymodule import myimportname as myalias`
self.register_name(alias, SymbolRole::Assigned)?;
} else {
self.register_name(&symbol.symbol, SymbolRole::Assigned)?;
}
}
}
}
}
}
ast::Statement::Return { value } => {
if let Some(expression) = value {
self.scan_expression(expression)?;
}
}
ast::Statement::Assert { test, msg } => {
self.scan_expression(test)?;
if let Some(expression) = msg {
self.scan_expression(expression)?;
}
}
ast::Statement::Delete { targets } => {
self.scan_expressions(targets)?;
}
ast::Statement::Assign { targets, value } => {
self.scan_expressions(targets)?;
self.scan_expression(value)?;
}
ast::Statement::AugAssign { target, value, .. } => {
self.scan_expression(target)?;
self.scan_expression(value)?;
}
ast::Statement::With { items, body } => {
for item in items {
self.scan_expression(&item.context_expr)?;
if let Some(expression) = &item.optional_vars {
self.scan_expression(expression)?;
}
}
self.scan_statements(body)?;
}
ast::Statement::Try {
body,
handlers,
orelse,
finalbody,
} => {
self.scan_statements(body)?;
for handler in handlers {
if let Some(expression) = &handler.typ {
self.scan_expression(expression)?;
}
if let Some(name) = &handler.name {
self.register_name(name, SymbolRole::Assigned)?;
}
self.scan_statements(&handler.body)?;
}
if let Some(code) = orelse {
self.scan_statements(code)?;
}
if let Some(code) = finalbody {
self.scan_statements(code)?;
}
}
ast::Statement::Raise { exception, cause } => {
if let Some(expression) = exception {
self.scan_expression(expression)?;
}
if let Some(expression) = cause {
self.scan_expression(expression)?;
}
}
}
Ok(())
}
fn scan_expressions(&mut self, expressions: &[ast::Expression]) -> SymbolTableResult {
for expression in expressions {
self.scan_expression(expression)?;
}
Ok(())
}
fn scan_expression(&mut self, expression: &ast::Expression) -> SymbolTableResult {
match expression {
ast::Expression::Binop { a, b, .. } => {
self.scan_expression(a)?;
self.scan_expression(b)?;
}
ast::Expression::BoolOp { a, b, .. } => {
self.scan_expression(a)?;
self.scan_expression(b)?;
}
ast::Expression::Compare { vals, .. } => {
self.scan_expressions(vals)?;
}
ast::Expression::Subscript { a, b } => {
self.scan_expression(a)?;
self.scan_expression(b)?;
}
ast::Expression::Attribute { value, .. } => {
self.scan_expression(value)?;
}
ast::Expression::Dict { elements } => {
for (key, value) in elements {
if let Some(key) = key {
self.scan_expression(key)?;
} else {
// dict unpacking marker
}
self.scan_expression(value)?;
}
}
ast::Expression::Await { value } => {
self.scan_expression(value)?;
}
ast::Expression::Yield { value } => {
if let Some(expression) = value {
self.scan_expression(expression)?;
}
}
ast::Expression::YieldFrom { value } => {
self.scan_expression(value)?;
}
ast::Expression::Unop { a, .. } => {
self.scan_expression(a)?;
}
ast::Expression::True
| ast::Expression::False
| ast::Expression::None
| ast::Expression::Ellipsis => {}
ast::Expression::Number { .. } => {}
ast::Expression::Starred { value } => {
self.scan_expression(value)?;
}
ast::Expression::Bytes { .. } => {}
ast::Expression::Tuple { elements }
| ast::Expression::Set { elements }
| ast::Expression::List { elements }
| ast::Expression::Slice { elements } => {
self.scan_expressions(elements)?;
}
ast::Expression::Comprehension { kind, generators } => {
match **kind {
ast::ComprehensionKind::GeneratorExpression { ref element }
| ast::ComprehensionKind::List { ref element }
| ast::ComprehensionKind::Set { ref element } => {
self.scan_expression(element)?;
}
ast::ComprehensionKind::Dict { ref key, ref value } => {
self.scan_expression(&key)?;
self.scan_expression(&value)?;
}
}
for generator in generators {
self.scan_expression(&generator.target)?;
self.scan_expression(&generator.iter)?;
for if_expr in &generator.ifs {
self.scan_expression(if_expr)?;
}
}
}
ast::Expression::Call {
function,
args,
keywords,
} => {
self.scan_expression(function)?;
self.scan_expressions(args)?;
for keyword in keywords {
self.scan_expression(&keyword.value)?;
}
}
ast::Expression::String { value } => {
self.scan_string_group(value)?;
}
ast::Expression::Identifier { name } => {
self.register_name(name, SymbolRole::Used)?;
}
ast::Expression::Lambda { args, body } => {
self.enter_function(args)?;
self.scan_expression(body)?;
self.leave_scope();
}
ast::Expression::IfExpression { test, body, orelse } => {
self.scan_expression(test)?;
self.scan_expression(body)?;
self.scan_expression(orelse)?;
}
}
Ok(())
}
fn enter_function(&mut self, args: &ast::Parameters) -> SymbolTableResult {
// Evaluate eventual default parameters:
self.scan_expressions(&args.defaults)?;
for kw_default in &args.kw_defaults {
if let Some(expression) = kw_default {
self.scan_expression(&expression)?;
}
}
// Annotations are scanned in outer scope:
self.scan_parameters_annotations(&args.args)?;
self.scan_parameters_annotations(&args.kwonlyargs)?;
if let ast::Varargs::Named(name) = &args.vararg {
self.scan_parameter_annotation(name)?;
}
if let ast::Varargs::Named(name) = &args.kwarg {
self.scan_parameter_annotation(name)?;
}
self.enter_scope();
// Fill scope with parameter names:
self.scan_parameters(&args.args)?;
self.scan_parameters(&args.kwonlyargs)?;
if let ast::Varargs::Named(name) = &args.vararg {
self.scan_parameter(name)?;
}
if let ast::Varargs::Named(name) = &args.kwarg {
self.scan_parameter(name)?;
}
Ok(())
}
fn scan_string_group(&mut self, group: &ast::StringGroup) -> SymbolTableResult {
match group {
ast::StringGroup::Constant { .. } => {}
ast::StringGroup::FormattedValue { value, .. } => {
self.scan_expression(value)?;
}
ast::StringGroup::Joined { values } => {
for subgroup in values {
self.scan_string_group(subgroup)?;
}
}
}
Ok(())
}
#[allow(clippy::single_match)]
fn register_name(&mut self, name: &str, role: SymbolRole) -> SymbolTableResult {
let scope_depth = self.scopes.len();
let current_scope = self.scopes.last_mut().unwrap();
let location = Default::default();
if current_scope.symbols.contains_key(name) {
// Role already set..
match role {
SymbolRole::Global => {
return Err(SymbolTableError {
error: format!("name '{}' is used prior to global declaration", name),
location,
})
}
SymbolRole::Nonlocal => {
return Err(SymbolTableError {
error: format!("name '{}' is used prior to nonlocal declaration", name),
location,
})
}
_ => {
// Ok?
}
}
} else {
match role {
SymbolRole::Nonlocal => {
if scope_depth < 2 {
return Err(SymbolTableError {
error: format!("cannot define nonlocal '{}' at top level.", name),
location,
});
}
}
_ => {
// Ok!
}
}
current_scope.symbols.insert(name.to_string(), role);
}
Ok(())
}
}

20
derive/Cargo.toml Normal file
View File

@@ -0,0 +1,20 @@
[package]
name = "rustpython-derive"
version = "0.1.0"
description = "Rust language extensions and macros specific to rustpython."
authors = ["RustPython Team"]
repository = "https://github.com/RustPython/RustPython"
license = "MIT"
edition = "2018"
[lib]
proc-macro = true
[dependencies]
syn = { version = "0.15.29", features = ["full"] }
quote = "0.6.11"
proc-macro2 = "0.4.27"
rustpython-compiler = { path = "../compiler", version = "0.1.0" }
rustpython-bytecode = { path = "../bytecode", version = "0.1.0" }
bincode = "1.1"
proc-macro-hack = "0.5"

View File

@@ -0,0 +1,174 @@
//! Parsing and processing for this form:
//! ```ignore
//! py_compile_input!(
//! // either:
//! source = "python_source_code",
//! // or
//! file = "file/path/relative/to/$CARGO_MANIFEST_DIR",
//!
//! // the mode to compile the code in
//! mode = "exec", // or "eval" or "single"
//! // the path put into the CodeObject, defaults to "frozen"
//! module_name = "frozen",
//! )
//! ```
use crate::{extract_spans, Diagnostic};
use bincode;
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::quote;
use rustpython_bytecode::bytecode::CodeObject;
use rustpython_compiler::compile;
use std::env;
use std::fs;
use std::path::PathBuf;
use syn::parse::{Parse, ParseStream, Result as ParseResult};
use syn::{self, parse2, Lit, LitByteStr, Meta, Token};
enum CompilationSourceKind {
File(PathBuf),
SourceCode(String),
}
struct CompilationSource {
kind: CompilationSourceKind,
span: (Span, Span),
}
impl CompilationSource {
fn compile(self, mode: &compile::Mode, module_name: String) -> Result<CodeObject, Diagnostic> {
let compile = |source| {
compile::compile(source, mode, module_name).map_err(|err| {
Diagnostic::spans_error(self.span, format!("Compile error: {}", err))
})
};
match &self.kind {
CompilationSourceKind::File(rel_path) => {
let mut path = PathBuf::from(
env::var_os("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR is not present"),
);
path.push(rel_path);
let source = fs::read_to_string(&path).map_err(|err| {
Diagnostic::spans_error(
self.span,
format!("Error reading file {:?}: {}", path, err),
)
})?;
compile(&source)
}
CompilationSourceKind::SourceCode(code) => compile(code),
}
}
}
/// This is essentially just a comma-separated list of Meta nodes, aka the inside of a MetaList.
struct PyCompileInput {
span: Span,
metas: Vec<Meta>,
}
impl PyCompileInput {
fn compile(&self) -> Result<CodeObject, Diagnostic> {
let mut module_name = None;
let mut mode = None;
let mut source: Option<CompilationSource> = None;
fn assert_source_empty(source: &Option<CompilationSource>) -> Result<(), Diagnostic> {
if let Some(source) = source {
Err(Diagnostic::spans_error(
source.span.clone(),
"Cannot have more than one source",
))
} else {
Ok(())
}
}
for meta in &self.metas {
match meta {
Meta::NameValue(name_value) => {
if name_value.ident == "mode" {
mode = Some(match &name_value.lit {
Lit::Str(s) => match s.value().as_str() {
"exec" => compile::Mode::Exec,
"eval" => compile::Mode::Eval,
"single" => compile::Mode::Single,
_ => bail_span!(s, "mode must be exec, eval, or single"),
},
_ => bail_span!(name_value.lit, "mode must be a string"),
})
} else if name_value.ident == "module_name" {
module_name = Some(match &name_value.lit {
Lit::Str(s) => s.value(),
_ => bail_span!(name_value.lit, "module_name must be string"),
})
} else if name_value.ident == "source" {
assert_source_empty(&source)?;
let code = match &name_value.lit {
Lit::Str(s) => s.value(),
_ => bail_span!(name_value.lit, "source must be a string"),
};
source = Some(CompilationSource {
kind: CompilationSourceKind::SourceCode(code),
span: extract_spans(&name_value).unwrap(),
});
} else if name_value.ident == "file" {
assert_source_empty(&source)?;
let path = match &name_value.lit {
Lit::Str(s) => PathBuf::from(s.value()),
_ => bail_span!(name_value.lit, "source must be a string"),
};
source = Some(CompilationSource {
kind: CompilationSourceKind::File(path),
span: extract_spans(&name_value).unwrap(),
});
}
}
_ => {}
}
}
source
.ok_or_else(|| {
Diagnostic::span_error(
self.span.clone(),
"Must have either file or source in py_compile_bytecode!()",
)
})?
.compile(
&mode.unwrap_or(compile::Mode::Exec),
module_name.unwrap_or_else(|| "frozen".to_string()),
)
}
}
impl Parse for PyCompileInput {
fn parse(input: ParseStream) -> ParseResult<Self> {
let span = input.cursor().span();
let metas = input
.parse_terminated::<Meta, Token![,]>(Meta::parse)?
.into_iter()
.collect();
Ok(PyCompileInput { span, metas })
}
}
pub fn impl_py_compile_bytecode(input: TokenStream2) -> Result<TokenStream2, Diagnostic> {
let input: PyCompileInput = parse2(input)?;
let code_obj = input.compile()?;
let bytes = bincode::serialize(&code_obj).expect("Failed to serialize");
let bytes = LitByteStr::new(&bytes, Span::call_site());
let output = quote! {
({
use ::rustpython_vm::__exports::bincode;
bincode::deserialize::<::rustpython_vm::bytecode::CodeObject>(#bytes)
.expect("Deserializing CodeObject failed")
})
};
Ok(output)
}

167
derive/src/error.rs Normal file
View File

@@ -0,0 +1,167 @@
// Taken from https://github.com/rustwasm/wasm-bindgen/blob/master/crates/backend/src/error.rs
//
// Copyright (c) 2014 Alex Crichton
//
// Permission is hereby granted, free of charge, to any
// person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the
// Software without restriction, including without
// limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice
// shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#![allow(dead_code)]
use proc_macro2::*;
use quote::{ToTokens, TokenStreamExt};
use syn::parse::Error;
macro_rules! err_span {
($span:expr, $($msg:tt)*) => (
$crate::Diagnostic::spanned_error(&$span, format!($($msg)*))
)
}
macro_rules! bail_span {
($($t:tt)*) => (
return Err(err_span!($($t)*).into())
)
}
macro_rules! push_err_span {
($diagnostics:expr, $($t:tt)*) => {
$diagnostics.push(err_span!($($t)*))
};
}
#[derive(Debug)]
pub struct Diagnostic {
inner: Repr,
}
#[derive(Debug)]
enum Repr {
Single {
text: String,
span: Option<(Span, Span)>,
},
SynError(Error),
Multi {
diagnostics: Vec<Diagnostic>,
},
}
impl Diagnostic {
pub fn error<T: Into<String>>(text: T) -> Diagnostic {
Diagnostic {
inner: Repr::Single {
text: text.into(),
span: None,
},
}
}
pub fn span_error<T: Into<String>>(span: Span, text: T) -> Diagnostic {
Diagnostic {
inner: Repr::Single {
text: text.into(),
span: Some((span, span)),
},
}
}
pub fn spans_error<T: Into<String>>(spans: (Span, Span), text: T) -> Diagnostic {
Diagnostic {
inner: Repr::Single {
text: text.into(),
span: Some(spans),
},
}
}
pub fn spanned_error<T: Into<String>>(node: &ToTokens, text: T) -> Diagnostic {
Diagnostic {
inner: Repr::Single {
text: text.into(),
span: extract_spans(node),
},
}
}
pub fn from_vec(diagnostics: Vec<Diagnostic>) -> Result<(), Diagnostic> {
if diagnostics.len() == 0 {
Ok(())
} else {
Err(Diagnostic {
inner: Repr::Multi { diagnostics },
})
}
}
#[allow(unconditional_recursion)]
pub fn panic(&self) -> ! {
match &self.inner {
Repr::Single { text, .. } => panic!("{}", text),
Repr::SynError(error) => panic!("{}", error),
Repr::Multi { diagnostics } => diagnostics[0].panic(),
}
}
}
impl From<Error> for Diagnostic {
fn from(err: Error) -> Diagnostic {
Diagnostic {
inner: Repr::SynError(err),
}
}
}
pub fn extract_spans(node: &dyn ToTokens) -> Option<(Span, Span)> {
let mut t = TokenStream::new();
node.to_tokens(&mut t);
let mut tokens = t.into_iter();
let start = tokens.next().map(|t| t.span());
let end = tokens.last().map(|t| t.span());
start.map(|start| (start, end.unwrap_or(start)))
}
impl ToTokens for Diagnostic {
fn to_tokens(&self, dst: &mut TokenStream) {
match &self.inner {
Repr::Single { text, span } => {
let cs2 = (Span::call_site(), Span::call_site());
let (start, end) = span.unwrap_or(cs2);
dst.append(Ident::new("compile_error", start));
dst.append(Punct::new('!', Spacing::Alone));
let mut message = TokenStream::new();
message.append(Literal::string(text));
let mut group = Group::new(Delimiter::Brace, message);
group.set_span(end);
dst.append(group);
}
Repr::Multi { diagnostics } => {
for diagnostic in diagnostics {
diagnostic.to_tokens(dst);
}
}
Repr::SynError(err) => {
err.to_compile_error().to_tokens(dst);
}
}
}
}

221
derive/src/from_args.rs Normal file
View File

@@ -0,0 +1,221 @@
use crate::Diagnostic;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::{
parse_quote, Attribute, Data, DeriveInput, Expr, Field, Fields, Ident, Lit, Meta, NestedMeta,
};
/// The kind of the python parameter, this corresponds to the value of Parameter.kind
/// (https://docs.python.org/3/library/inspect.html#inspect.Parameter.kind)
enum ParameterKind {
PositionalOnly,
PositionalOrKeyword,
KeywordOnly,
}
impl ParameterKind {
fn from_ident(ident: &Ident) -> Option<ParameterKind> {
if ident == "positional_only" {
Some(ParameterKind::PositionalOnly)
} else if ident == "positional_or_keyword" {
Some(ParameterKind::PositionalOrKeyword)
} else if ident == "keyword_only" {
Some(ParameterKind::KeywordOnly)
} else {
None
}
}
}
struct ArgAttribute {
kind: ParameterKind,
default: Option<Expr>,
optional: bool,
}
impl ArgAttribute {
fn from_attribute(attr: &Attribute) -> Option<Result<ArgAttribute, Diagnostic>> {
if !attr.path.is_ident("pyarg") {
return None;
}
let inner = move || match attr.parse_meta()? {
Meta::List(list) => {
let mut iter = list.nested.iter();
let first_arg = iter.next().ok_or_else(|| {
err_span!(list, "There must be at least one argument to #[pyarg()]")
})?;
let kind = match first_arg {
NestedMeta::Meta(Meta::Word(ident)) => ParameterKind::from_ident(ident),
_ => None,
};
let kind = kind.ok_or_else(|| {
err_span!(
first_arg,
"The first argument to #[pyarg()] must be the parameter type, either \
'positional_only', 'positional_or_keyword', or 'keyword_only'."
)
})?;
let mut attribute = ArgAttribute {
kind,
default: None,
optional: false,
};
while let Some(arg) = iter.next() {
attribute.parse_argument(arg)?;
}
if attribute.default.is_some() && attribute.optional {
bail_span!(attr, "Can't set both a default value and optional");
}
Ok(attribute)
}
_ => bail_span!(attr, "pyarg must be a list, like #[pyarg(...)]"),
};
Some(inner())
}
fn parse_argument(&mut self, arg: &NestedMeta) -> Result<(), Diagnostic> {
match arg {
NestedMeta::Meta(Meta::Word(ident)) => {
if ident == "default" {
if self.default.is_some() {
bail_span!(ident, "Default already set");
}
let expr = parse_quote!(Default::default());
self.default = Some(expr);
} else if ident == "optional" {
self.optional = true;
} else {
bail_span!(ident, "Unrecognised pyarg attribute");
}
}
NestedMeta::Meta(Meta::NameValue(name_value)) => {
if name_value.ident == "default" {
if self.default.is_some() {
bail_span!(name_value, "Default already set");
}
match name_value.lit {
Lit::Str(ref val) => {
let expr = val.parse::<Expr>().map_err(|_| {
err_span!(val, "Expected a valid expression for default argument")
})?;
self.default = Some(expr);
}
_ => bail_span!(name_value, "Expected string value for default argument"),
}
} else if name_value.ident == "optional" {
match name_value.lit {
Lit::Bool(ref val) => {
self.optional = val.value;
}
_ => bail_span!(
name_value.lit,
"Expected boolean value for optional argument"
),
}
} else {
bail_span!(name_value, "Unrecognised pyarg attribute");
}
}
_ => bail_span!(arg, "Unrecognised pyarg attribute"),
}
Ok(())
}
}
fn generate_field(field: &Field) -> Result<TokenStream2, Diagnostic> {
let mut pyarg_attrs = field
.attrs
.iter()
.filter_map(ArgAttribute::from_attribute)
.collect::<Result<Vec<_>, _>>()?;
let attr = if pyarg_attrs.is_empty() {
ArgAttribute {
kind: ParameterKind::PositionalOrKeyword,
default: None,
optional: false,
}
} else if pyarg_attrs.len() == 1 {
pyarg_attrs.remove(0)
} else {
bail_span!(field, "Multiple pyarg attributes on field");
};
let name = &field.ident;
let middle = quote! {
.map(|x| ::rustpython_vm::pyobject::TryFromObject::try_from_object(vm, x)).transpose()?
};
let ending = if let Some(default) = attr.default {
quote! {
.unwrap_or_else(|| #default)
}
} else if attr.optional {
quote! {
.map(::rustpython_vm::function::OptionalArg::Present)
.unwrap_or(::rustpython_vm::function::OptionalArg::Missing)
}
} else {
let err = match attr.kind {
ParameterKind::PositionalOnly | ParameterKind::PositionalOrKeyword => quote! {
::rustpython_vm::function::ArgumentError::TooFewArgs
},
ParameterKind::KeywordOnly => quote! {
::rustpython_vm::function::ArgumentError::RequiredKeywordArgument(tringify!(#name))
},
};
quote! {
.ok_or_else(|| #err)?
}
};
let file_output = match attr.kind {
ParameterKind::PositionalOnly => {
quote! {
#name: args.take_positional()#middle#ending,
}
}
ParameterKind::PositionalOrKeyword => {
quote! {
#name: args.take_positional_keyword(stringify!(#name))#middle#ending,
}
}
ParameterKind::KeywordOnly => {
quote! {
#name: args.take_keyword(stringify!(#name))#middle#ending,
}
}
};
Ok(file_output)
}
pub fn impl_from_args(input: DeriveInput) -> Result<TokenStream2, Diagnostic> {
let fields = match input.data {
Data::Struct(syn::DataStruct {
fields: Fields::Named(fields),
..
}) => fields
.named
.iter()
.map(generate_field)
.collect::<Result<TokenStream2, Diagnostic>>()?,
_ => bail_span!(input, "FromArgs input must be a struct with named fields"),
};
let name = input.ident;
let output = quote! {
impl ::rustpython_vm::function::FromArgs for #name {
fn from_args(
vm: &::rustpython_vm::VirtualMachine,
args: &mut ::rustpython_vm::function::PyFuncArgs
) -> Result<Self, ::rustpython_vm::function::ArgumentError> {
Ok(#name { #fields })
}
}
};
Ok(output)
}

55
derive/src/lib.rs Normal file
View File

@@ -0,0 +1,55 @@
#![recursion_limit = "128"]
extern crate proc_macro;
#[macro_use]
mod error;
mod compile_bytecode;
mod from_args;
mod pyclass;
use error::{extract_spans, Diagnostic};
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use proc_macro_hack::proc_macro_hack;
use quote::ToTokens;
use syn::{parse_macro_input, AttributeArgs, DeriveInput, Item};
fn result_to_tokens(result: Result<TokenStream2, Diagnostic>) -> TokenStream {
match result {
Ok(tokens) => tokens.into(),
Err(diagnostic) => diagnostic.into_token_stream().into(),
}
}
#[proc_macro_derive(FromArgs, attributes(pyarg))]
pub fn derive_from_args(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
result_to_tokens(from_args::impl_from_args(input))
}
#[proc_macro_attribute]
pub fn pyclass(attr: TokenStream, item: TokenStream) -> TokenStream {
let attr = parse_macro_input!(attr as AttributeArgs);
let item = parse_macro_input!(item as Item);
result_to_tokens(pyclass::impl_pyclass(attr, item))
}
#[proc_macro_attribute]
pub fn pyimpl(attr: TokenStream, item: TokenStream) -> TokenStream {
let attr = parse_macro_input!(attr as AttributeArgs);
let item = parse_macro_input!(item as Item);
result_to_tokens(pyclass::impl_pyimpl(attr, item))
}
#[proc_macro_attribute]
pub fn pystruct_sequence(attr: TokenStream, item: TokenStream) -> TokenStream {
let attr = parse_macro_input!(attr as AttributeArgs);
let item = parse_macro_input!(item as Item);
result_to_tokens(pyclass::impl_pystruct_sequence(attr, item))
}
#[proc_macro_hack]
pub fn py_compile_bytecode(input: TokenStream) -> TokenStream {
result_to_tokens(compile_bytecode::impl_py_compile_bytecode(input.into()))
}

463
derive/src/pyclass.rs Normal file
View File

@@ -0,0 +1,463 @@
use super::Diagnostic;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use std::collections::HashMap;
use syn::{
Attribute, AttributeArgs, Ident, ImplItem, Index, Item, Lit, Meta, MethodSig, NestedMeta,
};
enum ClassItem {
Method {
item_ident: Ident,
py_name: String,
},
ClassMethod {
item_ident: Ident,
py_name: String,
},
Property {
item_ident: Ident,
py_name: String,
setter: bool,
},
}
fn meta_to_vec(meta: Meta) -> Result<Vec<NestedMeta>, Meta> {
match meta {
Meta::Word(_) => Ok(Vec::new()),
Meta::List(list) => Ok(list.nested.into_iter().collect()),
Meta::NameValue(_) => Err(meta),
}
}
impl ClassItem {
fn extract_from_syn(
attrs: &mut Vec<Attribute>,
sig: &MethodSig,
) -> Result<Option<ClassItem>, Diagnostic> {
let mut item = None;
let mut attr_idx = None;
for (i, meta) in attrs
.iter()
.filter_map(|attr| attr.parse_meta().ok())
.enumerate()
{
let name = meta.name();
if name == "pymethod" {
if item.is_some() {
bail_span!(
sig.ident,
"You can only have one #[py*] attribute on an impl item"
)
}
let nesteds = meta_to_vec(meta).map_err(|meta| {
err_span!(
meta,
"#[pymethod = \"...\"] cannot be a name/value, you probably meant \
#[pymethod(name = \"...\")]",
)
})?;
let mut py_name = None;
for meta in nesteds {
let meta = match meta {
NestedMeta::Meta(meta) => meta,
NestedMeta::Literal(_) => continue,
};
match meta {
Meta::NameValue(name_value) => {
if name_value.ident == "name" {
if let Lit::Str(s) = &name_value.lit {
py_name = Some(s.value());
} else {
bail_span!(
&sig.ident,
"#[pymethod(name = ...)] must be a string"
);
}
}
}
_ => {}
}
}
item = Some(ClassItem::Method {
item_ident: sig.ident.clone(),
py_name: py_name.unwrap_or_else(|| sig.ident.to_string()),
});
attr_idx = Some(i);
} else if name == "pyclassmethod" {
if item.is_some() {
bail_span!(
sig.ident,
"You can only have one #[py*] attribute on an impl item"
)
}
let nesteds = meta_to_vec(meta).map_err(|meta| {
err_span!(
meta,
"#[pyclassmethod = \"...\"] cannot be a name/value, you probably meant \
#[pyclassmethod(name = \"...\")]",
)
})?;
let mut py_name = None;
for meta in nesteds {
let meta = match meta {
NestedMeta::Meta(meta) => meta,
NestedMeta::Literal(_) => continue,
};
match meta {
Meta::NameValue(name_value) => {
if name_value.ident == "name" {
if let Lit::Str(s) = &name_value.lit {
py_name = Some(s.value());
} else {
bail_span!(
&sig.ident,
"#[pyclassmethod(name = ...)] must be a string"
);
}
}
}
_ => {}
}
}
item = Some(ClassItem::ClassMethod {
item_ident: sig.ident.clone(),
py_name: py_name.unwrap_or_else(|| sig.ident.to_string()),
});
attr_idx = Some(i);
} else if name == "pyproperty" {
if item.is_some() {
bail_span!(
sig.ident,
"You can only have one #[py*] attribute on an impl item"
)
}
let nesteds = meta_to_vec(meta).map_err(|meta| {
err_span!(
meta,
"#[pyproperty = \"...\"] cannot be a name/value, you probably meant \
#[pyproperty(name = \"...\")]"
)
})?;
let mut setter = false;
let mut py_name = None;
for meta in nesteds {
let meta = match meta {
NestedMeta::Meta(meta) => meta,
NestedMeta::Literal(_) => continue,
};
match meta {
Meta::NameValue(name_value) => {
if name_value.ident == "name" {
if let Lit::Str(s) = &name_value.lit {
py_name = Some(s.value());
} else {
bail_span!(
&sig.ident,
"#[pyproperty(name = ...)] must be a string"
);
}
}
}
Meta::Word(ident) => {
if ident == "setter" {
setter = true;
}
}
_ => {}
}
}
let py_name = match py_name {
Some(py_name) => py_name,
None => {
let item_ident = sig.ident.to_string();
if setter {
if item_ident.starts_with("set_") {
let name = &item_ident["set_".len()..];
if name.is_empty() {
bail_span!(
&sig.ident,
"A #[pyproperty(setter)] fn with a set_* name must \
have something after \"set_\""
)
} else {
name.to_string()
}
} else {
bail_span!(
&sig.ident,
"A #[pyproperty(setter)] fn must either have a `name` \
parameter or a fn name along the lines of \"set_*\""
)
}
} else {
item_ident
}
}
};
item = Some(ClassItem::Property {
py_name,
item_ident: sig.ident.clone(),
setter,
});
attr_idx = Some(i);
}
}
if let Some(attr_idx) = attr_idx {
attrs.remove(attr_idx);
}
Ok(item)
}
}
pub fn impl_pyimpl(_attr: AttributeArgs, item: Item) -> Result<TokenStream2, Diagnostic> {
let mut imp = if let Item::Impl(imp) = item {
imp
} else {
return Ok(quote!(#item));
};
let mut diagnostics: Vec<Diagnostic> = Vec::new();
let items = imp
.items
.iter_mut()
.filter_map(|item| {
if let ImplItem::Method(meth) = item {
ClassItem::extract_from_syn(&mut meth.attrs, &meth.sig)
.map_err(|err| diagnostics.push(err))
.unwrap_or_default()
} else {
None
}
})
.collect::<Vec<_>>();
let ty = &imp.self_ty;
let mut properties: HashMap<&str, (Option<&Ident>, Option<&Ident>)> = HashMap::new();
for item in items.iter() {
match item {
ClassItem::Property {
ref item_ident,
ref py_name,
setter,
} => {
let entry = properties.entry(py_name).or_default();
let func = if *setter { &mut entry.1 } else { &mut entry.0 };
if func.is_some() {
bail_span!(
item_ident,
"Multiple property accessors with name {:?}",
py_name
)
}
*func = Some(item_ident);
}
_ => {}
}
}
let methods = items.iter().filter_map(|item| match item {
ClassItem::Method {
item_ident,
py_name,
} => Some(quote! {
class.set_str_attr(#py_name, ctx.new_rustfunc(Self::#item_ident));
}),
ClassItem::ClassMethod {
item_ident,
py_name,
} => Some(quote! {
class.set_str_attr(#py_name, ctx.new_classmethod(Self::#item_ident));
}),
_ => None,
});
let properties = properties
.iter()
.map(|(name, prop)| {
let getter = match prop.0 {
Some(getter) => getter,
None => {
push_err_span!(
diagnostics,
prop.1.unwrap(),
"Property {:?} is missing a getter",
name
);
return TokenStream2::new();
}
};
let add_setter = prop.1.map(|setter| quote!(.add_setter(Self::#setter)));
quote! {
class.set_str_attr(
#name,
::rustpython_vm::obj::objproperty::PropertyBuilder::new(ctx)
.add_getter(Self::#getter)
#add_setter
.create(),
);
}
})
.collect::<Vec<_>>();
Diagnostic::from_vec(diagnostics)?;
let ret = quote! {
#imp
impl ::rustpython_vm::pyobject::PyClassImpl for #ty {
fn impl_extend_class(
ctx: &::rustpython_vm::pyobject::PyContext,
class: &::rustpython_vm::obj::objtype::PyClassRef,
) {
#(#methods)*
#(#properties)*
}
}
};
Ok(ret)
}
fn generate_class_def(
ident: &Ident,
attr_name: &'static str,
attr: AttributeArgs,
attrs: &Vec<Attribute>,
) -> Result<TokenStream2, Diagnostic> {
let mut class_name = None;
for attr in attr {
if let NestedMeta::Meta(meta) = attr {
if let Meta::NameValue(name_value) = meta {
if name_value.ident == "name" {
if let Lit::Str(s) = name_value.lit {
class_name = Some(s.value());
} else {
bail_span!(
name_value.lit,
"#[{}(name = ...)] must be a string",
attr_name
);
}
}
}
}
}
let class_name = class_name.unwrap_or_else(|| ident.to_string());
let mut doc: Option<Vec<String>> = None;
for attr in attrs.iter() {
if attr.path.is_ident("doc") {
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();
match doc {
Some(ref mut doc) => doc.push(val),
None => doc = Some(vec![val]),
}
}
}
}
}
let doc = match doc {
Some(doc) => {
let doc = doc.join("\n");
quote!(Some(#doc))
}
None => quote!(None),
};
let ret = quote! {
impl ::rustpython_vm::pyobject::PyClassDef for #ident {
const NAME: &'static str = #class_name;
const DOC: Option<&'static str> = #doc;
}
};
Ok(ret)
}
pub fn impl_pyclass(attr: AttributeArgs, item: Item) -> Result<TokenStream2, Diagnostic> {
let (item, ident, attrs) = match item {
Item::Struct(struc) => (quote!(#struc), struc.ident, struc.attrs),
Item::Enum(enu) => (quote!(#enu), enu.ident, enu.attrs),
other => bail_span!(
other,
"#[pyclass] can only be on a struct or enum declaration"
),
};
let class_def = generate_class_def(&ident, "pyclass", attr, &attrs)?;
let ret = quote! {
#item
#class_def
};
Ok(ret)
}
pub fn impl_pystruct_sequence(attr: AttributeArgs, item: Item) -> Result<TokenStream2, Diagnostic> {
let struc = if let Item::Struct(struc) = item {
struc
} else {
bail_span!(
item,
"#[pystruct_sequence] can only be on a struct declaration"
)
};
let class_def = generate_class_def(&struc.ident, "pystruct_sequence", attr, &struc.attrs)?;
let mut properties = Vec::new();
let mut field_names = Vec::new();
for (i, field) in struc.fields.iter().enumerate() {
let idx = Index::from(i);
if let Some(ref field_name) = field.ident {
let field_name_str = field_name.to_string();
// TODO add doc to the generated property
let property = quote! {
class.set_str_attr(
#field_name_str,
::rustpython_vm::obj::objproperty::PropertyBuilder::new(ctx)
.add_getter(|zelf: &::rustpython_vm::obj::objtuple::PyTuple,
_vm: &::rustpython_vm::vm::VirtualMachine|
zelf.fast_getitem(#idx))
.create(),
);
};
properties.push(property);
field_names.push(quote!(#field_name));
} else {
field_names.push(quote!(#idx));
}
}
let ty = &struc.ident;
let ret = quote! {
#struc
#class_def
impl #ty {
fn into_struct_sequence(&self,
vm: &::rustpython_vm::vm::VirtualMachine,
cls: ::rustpython_vm::obj::objtype::PyClassRef,
) -> ::rustpython_vm::pyobject::PyResult<::rustpython_vm::obj::objtuple::PyTupleRef> {
let tuple: ::rustpython_vm::obj::objtuple::PyTuple =
vec![#(::rustpython_vm::pyobject::IntoPyObject
::into_pyobject(self.#field_names, vm)?
),*].into();
::rustpython_vm::pyobject::PyValue::into_ref_with_type(tuple, vm, cls)
}
}
impl ::rustpython_vm::pyobject::PyClassImpl for #ty {
fn impl_extend_class(
ctx: &::rustpython_vm::pyobject::PyContext,
class: &::rustpython_vm::obj::objtype::PyClassRef,
) {
#(#properties)*
}
fn make_class(
ctx: &::rustpython_vm::pyobject::PyContext
) -> ::rustpython_vm::obj::objtype::PyClassRef {
let py_class = ctx.new_class(<Self as ::rustpython_vm::pyobject::PyClassDef>::NAME, ctx.tuple_type());
Self::extend_class(ctx, &py_class);
py_class
}
}
};
Ok(ret)
}

View File

@@ -1,30 +0,0 @@
Byterun
* Builtins are exposted to frame.f_builtins
* f_builtins is assigned during frame creation,
self.f_builtins = f_locals['__builtins__']
if hasattr(self.f_builtins, '__dict__'):
self.f_builtins = self.f_builtins.__dict__
* f_locals has a __`____builtins___` field which is directly the `__builtins__` module
Jaspy
* The `module()` function creates either a NativeModule or PythonModule
* The objects in the module are PyType.native
* The function call is abstracted as a `call` function, which handles different
* IMPORT_NAME depends on `__import__()` in builtins
TODO:
* Implement a new type NativeFunction
* Wrap a function pointer in NativeFunction
* Refactor the CALL_FUNCTION case so it can call both python function and native function
* During frame creation, force push a nativefunction `print` into the namespace
* Modify LOAD_* so they can search for names in builtins
* Create a module type
* In VM initialization, load the builtins module into locals
* During frame creation, create a field that conatins the builtins dict

View File

@@ -1,17 +0,0 @@
https://wiki.python.org/moin/SimplePrograms
Simple HTTP Server
bottle.py
http://pypi-ranking.info/alltime
- simplejson
- pep8
- httplib2
- argparse
http://learning-python.com/books/lp4e-examples.html
https://docs.python.org/3/tutorial/introduction.html#numbers
http://doc.pypy.org/en/latest/getting-started-dev.html#running-pypy-s-unit-tests
CPython Regression suite
https://github.com/python/cpython/tree/master/Lib/test

View File

@@ -1,13 +0,0 @@
Create a frame class
change the environment to locals
turn run into run_code -> run_frame
TEST
Create a function class
implement MAKE_FUNCTION
implement CALL_FUNCTION
implement RETURN_VALUE
TEST function

View File

@@ -1,13 +0,0 @@
# TODO: other notes should be put into here
# getattr()
- Required by this opcode [LOAD_ATTR](https://docs.python.org/3/library/dis.html#opcode-LOAD_ATTR)
- The builtin function: https://docs.python.org/3/library/functions.html?highlight=getattr#getattr
-
# Memory management
- https://docs.python.org/3.6/c-api/memory.html
# Bootstraping
- http://doc.pypy.org/en/latest/coding-guide.html#our-runtime-interpreter-is-rpython
- http://www.aosabook.org/en/pypy.html

View File

@@ -1,5 +0,0 @@
Python bytecode: https://docs.python.org/3.4/library/dis.html
Python VM in python: https://github.com/nedbat/byterun
Python VM in JS: https://github.com/koehlma/jaspy
http://www.skulpt.org/

View File

@@ -1,43 +0,0 @@
# Sharing plan
## Topics
* Python architecture
* Compiler -> VM
* Flavors
* Cpython
* Pypy
* Byterun
* JSapy (?)
* Why Rust
* Security
* Learning
* Implementation plan
* VM first
* Compiler second
* Tools for study
* dis doc
* byterun doc
* bytrun code
* cpython source
---
* Python VM
* Stack machine
* Load add print
* dis
* Interpreter loop
* Python Types
* Control flow
* Jump
* If
* Loop
---
* Function call
* Frame
* Builtins

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 435 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

View File

@@ -1,286 +0,0 @@
class: center, middle
##Python Interpreter in Rust
#### 2017/8/6, COSCUP
#### Shing Lyu
???
top, middle, bottom
left, center, right
---
### About Me
* 呂行 Shing Lyu
* Mozilla engineer
* Servo team
![rust_and_servo](pic/rust-servo.png)
---
### Python's architecture
* Interpreted
* Garbage Collected
* Compiler => bytecode => VM
![python](pic/python-logo.png)
---
background-image: url('pic/ice-cream.jpg')
class: center, middle, bleed, text-bg
# Flavors
---
### Python Flavors
* CPython (THE python)
* Jython (JVM)
* IronPython (.NET)
* Pypy
* Educational
* Byterun
* Jsapy (JS)
* Brython (Python in browser)
---
class: center, middle
# Why & How?
---
### Why rewriting Python in Rust?
* Memory safety (?)
* Learn about Python's internal
* Learn to write Rust from scratch
* FUN!
---
### Implementation strategy
* Mostly follow CPython 3.6
* Focus on the VM first, then the compiler
* Use the Python built-in compiler to generate bytecode
* Focus on learning rather than usability
---
### Milestones
* Basic arithmetics
* Variables
* Control flows (require JUMP)
* Function call (require call stack)
* Built-in functions (require native code)
* Run Python tutorial example code <= We're here
* Exceptions
* GC
* Run popular libraries
---
class: center, middle, bleed, text-bg
background-image: url('pic/car_cutaway.jpg')
# Python Internals
---
### How Python VM works
* Stack machine
* Call stack and frames
* Has a NAMES list and CONSTS list
* Has a STACK as workspace
* Accepts Python bytecode
* `python -m dis source.py`
---
### A simple Python code
```
#!/usr/bin/env python3
print(1+1)
```
Running `python3 -m dis source.py` gives us
```
1 0 LOAD_NAME 0 (print)
3 LOAD_CONST 2 (2)
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP
10 LOAD_CONST 1 (None)
13 RETURN_VALUE
```
---
### LOAD_NAME "print"
* NAMES = ["print"]
* CONSTS = [None, 2]
* STACK:
```
| |
| print (native code)|
+--------------------+
```
---
### LOAD_CONST 2
* NAMES = ["print"]
* CONSTS = [None, 2]
* STACK:
```
| |
| 2 |
| print (native code)|
+--------------------+
```
---
### CALL_FUNCTION 1
1. `argument = stack.pop()` (argument == 2)
2. `function = stack.top()` (function == print)
3. call `print(2)`
* NAMES = ["print"]
* CONSTS = [None, 2]
* STACK:
```
| |
| print (native code)|
+--------------------+
```
---
### POP_TOP
* NAMES = ["print"]
* CONSTS = [None, 2]
* STACK:
```
| |
| (empty) |
+--------------------+
```
---
### LOAD_CONST None
* NAMES = ["print"]
* CONSTS = [None, 2]
* STACK:
```
| |
| None |
+--------------------+
```
---
### RETURN_VALUE
(returns top of stack == None)
---
class: center, middle, bleed, text-bg
background-image: url('pic/electronic_parts.jpg')
# Technical Detail
---
### Bytecode format
* `dis` output format is for human reader
* Implementing a `dis` format parser is a waste of time
* Emit JSON bytecode using the [bytecode](https://pypi.python.org/pypi/bytecode/0.5) module
```
code = compile(f,...) # Python built-in, return a Code object
bytecode.Bytecode()
.from_code(code)
.to_concrete_bytecode()
```
* Load into Rust using `serde_json`
---
### Types
* Everything is a `PyObject` in CPython
* We'll need that class hierarchy eventually
* Use a Rust `enum` for now
```
pub enum NativeType{
NoneType,
Boolean(bool),
Int(i32),
Str(String),
Tuple(Vec<NativeType>),
...
}
```
---
### Testing
* `assert` is essential to for unittests
* `assert` raises `AssertionError`
* Use `panic!()` before we implement exception
```
assert 1 == 1
```
```
1 0 LOAD_CONST 0 (1)
3 LOAD_CONST 0 (1)
6 COMPARE_OP 2 (==)
9 POP_JUMP_IF_TRUE 18
12 LOAD_GLOBAL 0 (AssertionError)
15 RAISE_VARARGS 1
>> 18 LOAD_CONST 1 (None)
21 RETURN_VALUE
```
---
### Native Function
* e.g. `print()`
```
pub enum NativeType {
NativeFunction(fn(Vec<NativeType>) -> NativeType),
...
}
match stack.pop() {
NativeFunction(func) => return_val = func(),
_ => ...
}
```
---
### Next steps
* Exceptions
* Make it run a small but popular tool/library
* Implement the parser
* Figure out garbage collection
* Performance benchmarking
---
### Contribute
## https://github.com/shinglyu/RustPython
![qr_code](pic/repo_QR.png)
---
class: middle, center
# Thank you
---
### References
* [`dis` documentation](https://docs.python.org/3.4/library/dis.html)
* [byterun](http://www.aosabook.org/en/500L/a-python-interpreter-written-in-python.html)
* [byterun (GitHub)](https://github.com/nedbat/byterun/)
* [cpython source code](https://github.com/python/cpython)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 KiB

View File

@@ -1,180 +0,0 @@
class: center, middle
##Python Interpreter in Rust
###Introduction
#### 2017/3/28
#### Shing Lyu
???
top, middle, bottom
left, center, right
---
name: toc
###Agenda
1. Category
1. Category
1. Category
1. Category
1. Category
1. Category
1. Category
???
This is a template
---
### Python's architecture
* Interpreted
* Garbage Collected
* Compiler => bytecode => VM
---
background-image: url('pic/ice-cream.jpg')
class: bleed
# Flavors
---
### Python Flavors
* CPython (THE python)
* Jython (JVM)
* IronPython (.NET)
* Pypy
* Educational
* Byterun
* Jsapy (JS)
* Brython (Python in browser)
---
### Why rewriting Python in Rust?
* Memory safety
* Learn about Python internal
* Learn real world Rust
---
### Implementation strategy
* Focus on the VM first, then the compiler
* Reuse the Python built-in compiler to generate bytecode
* Basic arithmetics
* Control flows (require JUMP)
* Function call (require call stack)
* Built-in functions (require native code)
* Run popular libraries
---
### References
* [`dis` documentation](https://docs.python.org/3.4/library/dis.html)
* [byterun](http://www.aosabook.org/en/500L/a-python-interpreter-written-in-python.html)
* [byterun (GitHub)](https://github.com/nedbat/byterun/)
* [cpython source code](https://github.com/python/cpython)
---
### How Python VM works
* Stack machine
* Accepts Python bytecode
* `python -m dis source.py`
---
### A simple Python code
```
#!/usr/bin/env python3
print(1+1)
```
We run `python3 -m dis source.py`
---
### The bytecode
```
1 0 LOAD_NAME 0 (print)
3 LOAD_CONST 2 (2)
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP
10 LOAD_CONST 1 (None)
13 RETURN_VALUE
```
---
### LOAD_NAME "print"
* NAMES = ["print"]
* CONSTS = [None, 2]
* STACK:
```
| |
| print (native code)|
+--------------------+
```
---
### LOAD_CONST 2
* NAMES = ["print"]
* CONSTS = [None, 2]
* STACK:
```
| |
| 2 |
| print (native code)|
+--------------------+
```
---
### CALL_FUNCTION 1
1. argument = stack.pop() (argument == 2)
2. function = stack.top() (function == print)
3. call print(2)
* NAMES = ["print"]
* CONSTS = [None, 2]
* STACK:
```
| |
| print (native code)|
+--------------------+
```
---
### POP_TOP
* NAMES = ["print"]
* CONSTS = [None, 2]
* STACK:
```
| |
| (empty) |
+--------------------+
```
---
### LOAD_CONST 1
* NAMES = ["print"]
* CONSTS = [None, 2]
* STACK:
```
| |
| None |
+--------------------+
```
---
### RETURN_VALUE
(returns top of stack == None)
---
### Next step
* Make it run a small but popular tool/library
* Implement the parser
* Performance benchmarking

View File

@@ -1,6 +0,0 @@
Topic to study
==================
* How to save a Rust Iterator on the stack?
* Study how blocks are handled in CPython.
* The `why` var?
* Why unwind everything when a `break` happened?

BIN
logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

4
parser/.gitignore vendored
View File

@@ -1,4 +0,0 @@
src/python.rs
target/
Cargo.lock

View File

@@ -1,16 +1,23 @@
[package]
name = "rustpython_parser"
version = "0.0.1"
authors = [ "Shing Lyu", "Windel Bouwman" ]
name = "rustpython-parser"
version = "0.1.0"
description = "Parser for python code."
authors = [ "RustPython Team" ]
build = "build.rs"
repository = "https://github.com/RustPython/RustPython"
license = "MIT"
edition = "2018"
[build-dependencies]
lalrpop="0.15.1"
lalrpop="0.16.3"
[dependencies]
lalrpop-util="0.15.1"
lalrpop-util="0.16.3"
log="0.4.1"
regex="0.2.2"
num-bigint = "0.2"
num-traits = "0.2"
unicode-xid = "0.1.0"
unic-emoji-char = "0.9.0"
serde = { version = "1.0.66", features = ["derive"] }
wtf8 = "0.0.3"

View File

@@ -1,5 +1,5 @@
extern crate lalrpop;
use lalrpop;
fn main() {
lalrpop::process_root().unwrap();
lalrpop::process_root().unwrap()
}

View File

@@ -4,6 +4,8 @@
pub use super::lexer::Location;
use num_bigint::BigInt;
use serde::{Deserialize, Serialize};
/*
#[derive(Debug)]
@@ -16,7 +18,7 @@ pub struct Node {
#[derive(Debug, PartialEq)]
pub enum Top {
Program(Program),
Statement(LocatedStatement),
Statement(Vec<LocatedStatement>),
Expression(Expression),
}
@@ -25,12 +27,18 @@ pub struct Program {
pub statements: Vec<LocatedStatement>,
}
#[derive(Debug, PartialEq)]
pub struct ImportSymbol {
pub symbol: String,
pub alias: Option<String>,
}
#[derive(Debug, PartialEq)]
pub struct SingleImport {
pub module: String,
// (symbol name in module, name it should be assigned locally)
pub symbol: Option<String>,
pub alias: Option<String>,
pub symbols: Vec<ImportSymbol>,
pub level: usize,
}
#[derive(Debug, PartialEq)]
@@ -42,12 +50,13 @@ pub struct Located<T> {
pub type LocatedStatement = Located<Statement>;
/// Abstract syntax tree nodes for python statements.
#[allow(clippy::large_enum_variant)]
#[derive(Debug, PartialEq)]
pub enum Statement {
Break,
Continue,
Return {
value: Option<Vec<Expression>>,
value: Option<Box<Expression>>,
},
Import {
import_parts: Vec<SingleImport>,
@@ -65,9 +74,9 @@ pub enum Statement {
value: Expression,
},
AugAssign {
target: Expression,
target: Box<Expression>,
op: Operator,
value: Expression,
value: Box<Expression>,
},
Expression {
expression: Expression,
@@ -94,7 +103,13 @@ pub enum Statement {
},
For {
target: Expression,
iter: Vec<Expression>,
iter: Expression,
body: Vec<LocatedStatement>,
orelse: Option<Vec<LocatedStatement>>,
},
AsyncFor {
target: Expression,
iter: Expression,
body: Vec<LocatedStatement>,
orelse: Option<Vec<LocatedStatement>>,
},
@@ -114,14 +129,20 @@ pub enum Statement {
bases: Vec<Expression>,
keywords: Vec<Keyword>,
decorator_list: Vec<Expression>,
// TODO: docstring: String,
},
FunctionDef {
name: String,
args: Parameters,
// docstring: String,
body: Vec<LocatedStatement>,
decorator_list: Vec<Expression>,
returns: Option<Expression>,
},
AsyncFunctionDef {
name: String,
args: Parameters,
body: Vec<LocatedStatement>,
decorator_list: Vec<Expression>,
returns: Option<Expression>,
},
}
@@ -151,6 +172,9 @@ pub enum Expression {
op: UnaryOperator,
a: Box<Expression>,
},
Await {
value: Box<Expression>,
},
Yield {
value: Option<Box<Expression>>,
},
@@ -158,9 +182,8 @@ pub enum Expression {
value: Box<Expression>,
},
Compare {
a: Box<Expression>,
op: Comparison,
b: Box<Expression>,
vals: Vec<Expression>,
ops: Vec<Comparison>,
},
Attribute {
value: Box<Expression>,
@@ -181,7 +204,7 @@ pub enum Expression {
elements: Vec<Expression>,
},
Dict {
elements: Vec<(Expression, Expression)>,
elements: Vec<(Option<Expression>, Expression)>,
},
Set {
elements: Vec<Expression>,
@@ -197,7 +220,7 @@ pub enum Expression {
elements: Vec<Expression>,
},
String {
value: String,
value: StringGroup,
},
Bytes {
value: Vec<u8>,
@@ -217,22 +240,75 @@ pub enum Expression {
True,
False,
None,
Ellipsis,
}
impl Expression {
/// Returns a short name for the node suitable for use in error messages.
pub fn name(&self) -> &'static str {
use self::Expression::*;
use self::StringGroup::*;
match self {
BoolOp { .. } | Binop { .. } | Unop { .. } => "operator",
Subscript { .. } => "subscript",
Await { .. } => "await expression",
Yield { .. } | YieldFrom { .. } => "yield expression",
Compare { .. } => "comparison",
Attribute { .. } => "attribute",
Call { .. } => "function call",
Number { .. }
| String {
value: Constant { .. },
}
| Bytes { .. } => "literal",
List { .. } => "list",
Tuple { .. } => "tuple",
Dict { .. } => "dict display",
Set { .. } => "set display",
Comprehension { kind, .. } => match **kind {
ComprehensionKind::List { .. } => "list comprehension",
ComprehensionKind::Dict { .. } => "dict comprehension",
ComprehensionKind::Set { .. } => "set comprehension",
ComprehensionKind::GeneratorExpression { .. } => "generator expression",
},
Starred { .. } => "starred",
Slice { .. } => "slice",
String {
value: Joined { .. },
}
| String {
value: FormattedValue { .. },
} => "f-string expression",
Identifier { .. } => "named expression",
Lambda { .. } => "lambda",
IfExpression { .. } => "conditional expression",
True | False | None => "keyword",
Ellipsis => "ellipsis",
}
}
}
/*
* In cpython this is called arguments, but we choose parameters to
* distuingish between function parameters and actual call arguments.
* distinguish between function parameters and actual call arguments.
*/
#[derive(Debug, PartialEq, Default)]
pub struct Parameters {
pub args: Vec<String>,
pub kwonlyargs: Vec<String>,
pub vararg: Option<Option<String>>, // Optionally we handle optionally named '*args' or '*'
pub kwarg: Option<Option<String>>,
pub args: Vec<Parameter>,
pub kwonlyargs: Vec<Parameter>,
pub vararg: Varargs, // Optionally we handle optionally named '*args' or '*'
pub kwarg: Varargs,
pub defaults: Vec<Expression>,
pub kw_defaults: Vec<Option<Expression>>,
}
#[derive(Debug, PartialEq, Default)]
pub struct Parameter {
pub arg: String,
pub annotation: Option<Box<Expression>>,
}
#[derive(Debug, PartialEq)]
pub enum ComprehensionKind {
GeneratorExpression { element: Expression },
@@ -312,3 +388,54 @@ pub enum Number {
Float { value: f64 },
Complex { real: f64, imag: f64 },
}
/// Transforms a value prior to formatting it.
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ConversionFlag {
/// Converts by calling `str(<value>)`.
Str,
/// Converts by calling `ascii(<value>)`.
Ascii,
/// Converts by calling `repr(<value>)`.
Repr,
}
#[derive(Debug, PartialEq)]
pub enum StringGroup {
Constant {
value: String,
},
FormattedValue {
value: Box<Expression>,
conversion: Option<ConversionFlag>,
spec: String,
},
Joined {
values: Vec<StringGroup>,
},
}
#[derive(Debug, PartialEq)]
pub enum Varargs {
None,
Unnamed,
Named(Parameter),
}
impl Default for Varargs {
fn default() -> Varargs {
Varargs::None
}
}
impl From<Option<Option<Parameter>>> for Varargs {
fn from(opt: Option<Option<Parameter>>) -> Varargs {
match opt {
Some(inner_opt) => match inner_opt {
Some(param) => Varargs::Named(param),
None => Varargs::Unnamed,
},
None => Varargs::None,
}
}
}

91
parser/src/error.rs Normal file
View File

@@ -0,0 +1,91 @@
//! Define internal parse error types
//! The goal is to provide a matching and a safe error API, maksing errors from LALR
extern crate lalrpop_util;
use self::lalrpop_util::ParseError as InnerError;
use crate::lexer::{LexicalError, LexicalErrorType, Location};
use crate::token::Tok;
use std::error::Error;
use std::fmt;
/// Represents an error during parsing
#[derive(Debug, PartialEq)]
pub struct ParseError {
pub error: ParseErrorType,
pub location: Location,
}
#[derive(Debug, PartialEq)]
pub enum ParseErrorType {
/// Parser encountered an unexpected end of input
EOF,
/// Parser encountered an extra token
ExtraToken(Tok),
/// Parser encountered an invalid token
InvalidToken,
/// Parser encountered an unexpected token
UnrecognizedToken(Tok, Vec<String>),
/// Maps to `User` type from `lalrpop-util`
Lexical(LexicalErrorType),
}
/// Convert `lalrpop_util::ParseError` to our internal type
impl From<InnerError<Location, Tok, LexicalError>> for ParseError {
fn from(err: InnerError<Location, Tok, LexicalError>) -> Self {
match err {
// TODO: Are there cases where this isn't an EOF?
InnerError::InvalidToken { location } => ParseError {
error: ParseErrorType::EOF,
location,
},
InnerError::ExtraToken { token } => ParseError {
error: ParseErrorType::ExtraToken(token.1),
location: token.0,
},
InnerError::User { error } => ParseError {
error: ParseErrorType::Lexical(error.error),
location: error.location,
},
InnerError::UnrecognizedToken { token, expected } => {
match token {
Some(tok) => ParseError {
error: ParseErrorType::UnrecognizedToken(tok.1, expected),
location: tok.0,
},
// EOF was observed when it was unexpected
None => ParseError {
error: ParseErrorType::EOF,
location: Default::default(),
},
}
}
}
}
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} at {}", self.error, self.location)
}
}
impl fmt::Display for ParseErrorType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ParseErrorType::EOF => write!(f, "Got unexpected EOF"),
ParseErrorType::ExtraToken(ref tok) => write!(f, "Got extraneous token: {:?}", tok),
ParseErrorType::InvalidToken => write!(f, "Got invalid token"),
ParseErrorType::UnrecognizedToken(ref tok, _) => {
write!(f, "Got unexpected token: {:?}", tok)
}
ParseErrorType::Lexical(ref error) => write!(f, "{}", error),
}
}
}
impl Error for ParseError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}
}

237
parser/src/fstring.rs Normal file
View File

@@ -0,0 +1,237 @@
use std::iter;
use std::mem;
use std::str;
use lalrpop_util::ParseError as LalrpopError;
use crate::ast::{ConversionFlag, StringGroup};
use crate::lexer::{LexicalError, LexicalErrorType, Location, Tok};
use crate::parser::parse_expression;
use self::FStringError::*;
use self::StringGroup::*;
// TODO: consolidate these with ParseError
#[derive(Debug, PartialEq)]
pub enum FStringError {
UnclosedLbrace,
UnopenedRbrace,
InvalidExpression,
InvalidConversionFlag,
EmptyExpression,
MismatchedDelimiter,
}
impl From<FStringError> for LalrpopError<Location, Tok, LexicalError> {
fn from(_err: FStringError) -> Self {
lalrpop_util::ParseError::User {
error: LexicalError {
error: LexicalErrorType::StringError,
location: Default::default(),
},
}
}
}
struct FStringParser<'a> {
chars: iter::Peekable<str::Chars<'a>>,
}
impl<'a> FStringParser<'a> {
fn new(source: &'a str) -> Self {
Self {
chars: source.chars().peekable(),
}
}
fn parse_formatted_value(&mut self) -> Result<StringGroup, FStringError> {
let mut expression = String::new();
let mut spec = String::new();
let mut delims = Vec::new();
let mut conversion = None;
while let Some(ch) = self.chars.next() {
match ch {
'!' if delims.is_empty() => {
conversion = Some(match self.chars.next() {
Some('s') => ConversionFlag::Str,
Some('a') => ConversionFlag::Ascii,
Some('r') => ConversionFlag::Repr,
Some(_) => {
return Err(InvalidConversionFlag);
}
None => {
break;
}
})
}
':' if delims.is_empty() => {
while let Some(&next) = self.chars.peek() {
if next != '}' {
spec.push(next);
self.chars.next();
} else {
break;
}
}
}
'(' | '{' | '[' => {
expression.push(ch);
delims.push(ch);
}
')' => {
if delims.pop() != Some('(') {
return Err(MismatchedDelimiter);
}
expression.push(ch);
}
']' => {
if delims.pop() != Some('[') {
return Err(MismatchedDelimiter);
}
expression.push(ch);
}
'}' if !delims.is_empty() => {
if delims.pop() != Some('{') {
return Err(MismatchedDelimiter);
}
expression.push(ch);
}
'}' => {
if expression.is_empty() {
return Err(EmptyExpression);
}
return Ok(FormattedValue {
value: Box::new(
parse_expression(expression.trim()).map_err(|_| InvalidExpression)?,
),
conversion,
spec,
});
}
'"' | '\'' => {
expression.push(ch);
while let Some(next) = self.chars.next() {
expression.push(next);
if next == ch {
break;
}
}
}
_ => {
expression.push(ch);
}
}
}
Err(UnclosedLbrace)
}
fn parse(mut self) -> Result<StringGroup, FStringError> {
let mut content = String::new();
let mut values = vec![];
while let Some(ch) = self.chars.next() {
match ch {
'{' => {
if let Some('{') = self.chars.peek() {
self.chars.next();
content.push('{');
} else {
if !content.is_empty() {
values.push(Constant {
value: mem::replace(&mut content, String::new()),
});
}
values.push(self.parse_formatted_value()?);
}
}
'}' => {
if let Some('}') = self.chars.peek() {
self.chars.next();
content.push('}');
} else {
return Err(UnopenedRbrace);
}
}
_ => {
content.push(ch);
}
}
}
if !content.is_empty() {
values.push(Constant { value: content })
}
Ok(match values.len() {
0 => Constant {
value: String::new(),
},
1 => values.into_iter().next().unwrap(),
_ => Joined { values },
})
}
}
pub fn parse_fstring(source: &str) -> Result<StringGroup, FStringError> {
FStringParser::new(source).parse()
}
#[cfg(test)]
mod tests {
use crate::ast;
use super::*;
fn mk_ident(name: &str) -> ast::Expression {
ast::Expression::Identifier {
name: name.to_owned(),
}
}
#[test]
fn test_parse_fstring() {
let source = String::from("{a}{ b }{{foo}}");
let parse_ast = parse_fstring(&source).unwrap();
assert_eq!(
parse_ast,
Joined {
values: vec![
FormattedValue {
value: Box::new(mk_ident("a")),
conversion: None,
spec: String::new(),
},
FormattedValue {
value: Box::new(mk_ident("b")),
conversion: None,
spec: String::new(),
},
Constant {
value: "{foo}".to_owned()
}
]
}
);
}
#[test]
fn test_parse_empty_fstring() {
assert_eq!(
parse_fstring(""),
Ok(Constant {
value: String::new(),
}),
);
}
#[test]
fn test_parse_invalid_fstring() {
assert_eq!(parse_fstring("{"), Err(UnclosedLbrace));
assert_eq!(parse_fstring("}"), Err(UnopenedRbrace));
assert_eq!(parse_fstring("{class}"), Err(InvalidExpression));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,14 @@
#[macro_use]
extern crate log;
extern crate num_bigint;
extern crate num_traits;
use lalrpop_util::lalrpop_mod;
pub mod ast;
pub mod error;
mod fstring;
pub mod lexer;
pub mod parser;
mod python;
lalrpop_mod!(
#[allow(clippy::all)]
python
);
pub mod token;
pub use self::parser::parse;

View File

@@ -1,30 +1,10 @@
extern crate lalrpop_util;
use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::iter;
use std::path::Path;
use super::ast;
use super::lexer;
use super::python;
use super::token;
pub fn read_file(filename: &Path) -> Result<String, String> {
info!("Loading file {:?}", filename);
match File::open(&filename) {
Ok(mut file) => {
let mut s = String::new();
match file.read_to_string(&mut s) {
Err(why) => Err(String::from("Reading file failed: ") + why.description()),
Ok(_) => Ok(s),
}
}
Err(why) => Err(String::from("Opening file failed: ") + why.description()),
}
}
use crate::ast;
use crate::error::ParseError;
use crate::lexer;
use crate::python;
use crate::token;
/*
* Parse python code.
@@ -32,13 +12,6 @@ pub fn read_file(filename: &Path) -> Result<String, String> {
* https://github.com/antlr/grammars-v4/tree/master/python3
*/
pub fn parse(filename: &Path) -> Result<ast::Program, String> {
info!("Parsing: {}", filename.display());
let txt = read_file(filename)?;
debug!("Read contents of file: {}", txt);
parse_program(&txt)
}
macro_rules! do_lalr_parsing {
($input: expr, $pat: ident, $tok: ident) => {{
let lxr = lexer::make_tokenizer($input);
@@ -46,7 +19,7 @@ macro_rules! do_lalr_parsing {
let tokenizer = iter::once(Ok(marker_token)).chain(lxr);
match python::TopParser::new().parse(tokenizer) {
Err(why) => Err(format!("{:?}", why)),
Err(err) => Err(ParseError::from(err)),
Ok(top) => {
if let ast::Top::$pat(x) = top {
Ok(x)
@@ -58,11 +31,11 @@ macro_rules! do_lalr_parsing {
}};
}
pub fn parse_program(source: &str) -> Result<ast::Program, String> {
pub fn parse_program(source: &str) -> Result<ast::Program, ParseError> {
do_lalr_parsing!(source, Program, StartProgram)
}
pub fn parse_statement(source: &str) -> Result<ast::LocatedStatement, String> {
pub fn parse_statement(source: &str) -> Result<Vec<ast::LocatedStatement>, ParseError> {
do_lalr_parsing!(source, Statement, StartStatement)
}
@@ -71,7 +44,6 @@ pub fn parse_statement(source: &str) -> Result<ast::LocatedStatement, String> {
/// # Example
/// ```
/// extern crate num_bigint;
/// extern crate rustpython_parser;
/// use num_bigint::BigInt;
/// use rustpython_parser::{parser, ast};
/// let expr = parser::parse_expression("1+2").unwrap();
@@ -88,7 +60,7 @@ pub fn parse_statement(source: &str) -> Result<ast::LocatedStatement, String> {
/// expr);
///
/// ```
pub fn parse_expression(source: &str) -> Result<ast::Expression, String> {
pub fn parse_expression(source: &str) -> Result<ast::Expression, ParseError> {
do_lalr_parsing!(source, Expression, StartExpression)
}
@@ -103,7 +75,6 @@ mod tests {
#[test]
fn test_parse_empty() {
let parse_ast = parse_program(&String::from("\n"));
assert_eq!(parse_ast, Ok(ast::Program { statements: vec![] }))
}
@@ -122,7 +93,9 @@ mod tests {
name: String::from("print"),
}),
args: vec![ast::Expression::String {
value: String::from("Hello world"),
value: ast::StringGroup::Constant {
value: String::from("Hello world")
}
}],
keywords: vec![],
},
@@ -148,7 +121,9 @@ mod tests {
}),
args: vec![
ast::Expression::String {
value: String::from("Hello world"),
value: ast::StringGroup::Constant {
value: String::from("Hello world"),
}
},
ast::Expression::Number {
value: ast::Number::Integer {
@@ -179,7 +154,9 @@ mod tests {
name: String::from("my_func"),
}),
args: vec![ast::Expression::String {
value: String::from("positional"),
value: ast::StringGroup::Constant {
value: String::from("positional"),
}
}],
keywords: vec![ast::Keyword {
name: Some("keyword".to_string()),
@@ -202,7 +179,7 @@ mod tests {
let parse_ast = parse_statement(&source).unwrap();
assert_eq!(
parse_ast,
ast::LocatedStatement {
vec![ast::LocatedStatement {
location: ast::Location::new(1, 1),
node: ast::Statement::If {
test: ast::Expression::Number {
@@ -251,7 +228,7 @@ mod tests {
}
},]),
}
}
}]
);
}
@@ -261,15 +238,24 @@ mod tests {
let parse_ast = parse_statement(&source);
assert_eq!(
parse_ast,
Ok(ast::LocatedStatement {
Ok(vec![ast::LocatedStatement {
location: ast::Location::new(1, 1),
node: ast::Statement::Expression {
expression: ast::Expression::Lambda {
args: ast::Parameters {
args: vec![String::from("x"), String::from("y")],
args: vec![
ast::Parameter {
arg: String::from("x"),
annotation: None,
},
ast::Parameter {
arg: String::from("y"),
annotation: None,
}
],
kwonlyargs: vec![],
vararg: None,
kwarg: None,
vararg: ast::Varargs::None,
kwarg: ast::Varargs::None,
defaults: vec![],
kw_defaults: vec![],
},
@@ -284,7 +270,7 @@ mod tests {
})
}
}
})
}])
)
}
@@ -294,7 +280,7 @@ mod tests {
assert_eq!(
parse_statement(&source),
Ok(ast::LocatedStatement {
Ok(vec![ast::LocatedStatement {
location: ast::Location::new(1, 1),
node: ast::Statement::Assign {
targets: vec![ast::Expression::Tuple {
@@ -322,16 +308,18 @@ mod tests {
]
}
}
})
}])
)
}
#[test]
fn test_parse_class() {
let source = String::from("class Foo(A, B):\n def __init__(self):\n pass\n def method_with_default(self, arg='default'):\n pass\n");
let source = String::from(
"class Foo(A, B):\n def __init__(self):\n pass\n def method_with_default(self, arg='default'):\n pass\n",
);
assert_eq!(
parse_statement(&source),
Ok(ast::LocatedStatement {
Ok(vec![ast::LocatedStatement {
location: ast::Location::new(1, 1),
node: ast::Statement::ClassDef {
name: String::from("Foo"),
@@ -350,10 +338,13 @@ mod tests {
node: ast::Statement::FunctionDef {
name: String::from("__init__"),
args: ast::Parameters {
args: vec![String::from("self")],
args: vec![ast::Parameter {
arg: String::from("self"),
annotation: None,
}],
kwonlyargs: vec![],
vararg: None,
kwarg: None,
vararg: ast::Varargs::None,
kwarg: ast::Varargs::None,
defaults: vec![],
kw_defaults: vec![],
},
@@ -362,6 +353,7 @@ mod tests {
node: ast::Statement::Pass,
}],
decorator_list: vec![],
returns: None,
}
},
ast::LocatedStatement {
@@ -369,12 +361,23 @@ mod tests {
node: ast::Statement::FunctionDef {
name: String::from("method_with_default"),
args: ast::Parameters {
args: vec![String::from("self"), String::from("arg"),],
args: vec![
ast::Parameter {
arg: String::from("self"),
annotation: None,
},
ast::Parameter {
arg: String::from("arg"),
annotation: None,
}
],
kwonlyargs: vec![],
vararg: None,
kwarg: None,
vararg: ast::Varargs::None,
kwarg: ast::Varargs::None,
defaults: vec![ast::Expression::String {
value: "default".to_string()
value: ast::StringGroup::Constant {
value: "default".to_string()
}
}],
kw_defaults: vec![],
},
@@ -383,12 +386,13 @@ mod tests {
node: ast::Statement::Pass,
}],
decorator_list: vec![],
returns: None,
}
}
],
decorator_list: vec![],
}
})
}])
)
}
@@ -455,26 +459,30 @@ mod tests {
},
ifs: vec![
ast::Expression::Compare {
a: Box::new(ast::Expression::Identifier {
name: "a".to_string()
}),
op: ast::Comparison::Less,
b: Box::new(ast::Expression::Number {
value: ast::Number::Integer {
value: BigInt::from(5)
vals: vec![
ast::Expression::Identifier {
name: "a".to_string()
},
ast::Expression::Number {
value: ast::Number::Integer {
value: BigInt::from(5)
}
}
}),
],
ops: vec![ast::Comparison::Less],
},
ast::Expression::Compare {
a: Box::new(ast::Expression::Identifier {
name: "a".to_string()
}),
op: ast::Comparison::Greater,
b: Box::new(ast::Expression::Number {
value: ast::Number::Integer {
value: BigInt::from(10)
vals: vec![
ast::Expression::Identifier {
name: "a".to_string()
},
ast::Expression::Number {
value: ast::Number::Integer {
value: BigInt::from(10)
}
}
}),
],
ops: vec![ast::Comparison::Greater],
},
],
}

View File

@@ -2,11 +2,13 @@
// See also: https://github.com/antlr/grammars-v4/blob/master/python3/Python3.g4
// See also: file:///usr/share/doc/python/html/reference/compound_stmts.html#function-definitions
// See also: https://greentreesnakes.readthedocs.io/en/latest/nodes.html#keyword
#![allow(unknown_lints,clippy)]
use super::ast;
use super::lexer;
use std::iter::FromIterator;
use crate::ast;
use crate::fstring::parse_fstring;
use crate::lexer;
use num_bigint::BigInt;
grammar;
@@ -22,29 +24,32 @@ pub Top: ast::Top = {
Program: ast::Program = {
<lines:FileLine*> => ast::Program {
statements: Vec::from_iter(lines.into_iter().filter_map(|e| e))
statements: Vec::from_iter(lines.into_iter().flatten())
},
};
// A file line either has a declaration, or an empty newline:
FileLine: Option<ast::LocatedStatement> = {
<s:Statement> => Some(s),
"\n" => None,
FileLine: Vec<ast::LocatedStatement> = {
Statement,
"\n" => vec![],
};
Suite: Vec<ast::LocatedStatement> = {
<s:SimpleStatement> => vec![s],
"\n" indent <s:Statement+> dedent => s,
};
Statement: ast::LocatedStatement = {
SimpleStatement,
CompoundStatement,
"\n" indent <s:Statement+> dedent => s.into_iter().flatten().collect(),
};
SimpleStatement: ast::LocatedStatement = {
<s:SmallStatement> "\n" => s,
<s:SmallStatement> ";" => s,
Statement: Vec<ast::LocatedStatement> = {
SimpleStatement,
<s:CompoundStatement> => vec![s],
};
SimpleStatement: Vec<ast::LocatedStatement> = {
<s1:SmallStatement> <s2:(";" SmallStatement)*> ";"? "\n" => {
let mut statements = vec![s1];
statements.extend(s2.into_iter().map(|e| e.1));
statements
}
};
SmallStatement: ast::LocatedStatement = {
@@ -100,42 +105,30 @@ ExpressionStatement: ast::LocatedStatement = {
}
}
},
<loc:@L> <expr:TestOrStarExprList> <op:AugAssign> <e2:TestList> => {
// TODO: this works in most cases:
let rhs = e2.into_iter().next().unwrap();
<loc:@L> <expr:TestOrStarExprList> <op:AugAssign> <rhs:TestList> => {
ast::LocatedStatement {
location: loc,
node: ast::Statement::AugAssign { target: expr, op: op, value: rhs },
node: ast::Statement::AugAssign {
target: Box::new(expr),
op,
value: Box::new(rhs)
},
}
},
};
AssignSuffix: ast::Expression = {
"=" <e:TestList> => {
if e.len() > 1 {
ast::Expression::Tuple {
elements: e
}
} else {
e.into_iter().next().unwrap()
}
},
"=" <e:TestList> => e,
"=" <e:YieldExpr> => e,
};
TestOrStarExprList: ast::Expression = {
<e:TestOrStarExpr> <e2:("," TestOrStarExpr)*> <comma:","?> => {
let mut res = vec![e];
res.extend(e2.into_iter().map(|x| x.1));
// First build tuple from first item:
let expr = if (res.len() > 1) || comma.is_some() {
ast::Expression::Tuple { elements: res }
<elements:OneOrMore<TestOrStarExpr>> <comma:","?> => {
if elements.len() == 1 && comma.is_none() {
elements.into_iter().next().unwrap()
} else {
res.into_iter().next().unwrap()
};
expr
ast::Expression::Tuple { elements }
}
}
};
@@ -176,7 +169,7 @@ FlowStatement: ast::LocatedStatement = {
<loc:@L> "return" <t:TestList?> => {
ast::LocatedStatement {
location: loc,
node: ast::Statement::Return { value: t },
node: ast::Statement::Return { value: t.map(Box::new) },
}
},
<loc:@L> <y:YieldExpr> => {
@@ -213,8 +206,9 @@ ImportStatement: ast::LocatedStatement = {
.map(|(n, a)|
ast::SingleImport {
module: n.to_string(),
symbol: None,
alias: a.clone()
symbols: vec![],
alias: a.clone(),
level: 0,
})
.collect()
},
@@ -224,35 +218,30 @@ ImportStatement: ast::LocatedStatement = {
ast::LocatedStatement {
location: loc,
node: ast::Statement::Import {
import_parts: i
.iter()
.map(|(i, a)|
ast::SingleImport {
module: n.to_string(),
symbol: Some(i.to_string()),
alias: a.clone()
})
.collect()
import_parts: vec![
ast::SingleImport {
module: n.0.to_string(),
symbols: i.iter()
.map(|(i, a)|
ast::ImportSymbol {
symbol: i.to_string(),
alias: a.clone(),
})
.collect(),
alias: None,
level: n.1
}]
},
}
},
};
ImportFromLocation: String = {
ImportFromLocation: (String, usize) = {
<dots: "."*> <name:DottedName> => {
let mut r = "".to_string();
for _dot in dots {
r.push_str(".");
}
r.push_str(&name);
r
(name, dots.len())
},
<dots: "."+> => {
let mut r = "".to_string();
for _dot in dots {
r.push_str(".");
}
r
("".to_string(), dots.len())
},
};
@@ -303,15 +292,11 @@ NonlocalStatement: ast::LocatedStatement = {
};
AssertStatement: ast::LocatedStatement = {
<loc:@L> "assert" <t:Test> <m: ("," Test)?> => {
<loc:@L> "assert" <test:Test> <msg: ("," Test)?> => {
ast::LocatedStatement {
location: loc,
node: ast::Statement::Assert {
test: t,
msg: match m {
Some(e) => Some(e.1),
None => None,
}
test, msg: msg.map(|e| e.1)
}
}
},
@@ -328,12 +313,9 @@ CompoundStatement: ast::LocatedStatement = {
};
IfStatement: ast::LocatedStatement = {
<loc:@L> "if" <t:Test> ":" <s1:Suite> <s2:(@L "elif" Test ":" Suite)*> <s3:("else" ":" Suite)?> => {
<loc:@L> "if" <test:Test> ":" <s1:Suite> <s2:(@L "elif" Test ":" Suite)*> <s3:("else" ":" Suite)?> => {
// Determine last else:
let mut last = match s3 {
Some(s) => Some(s.2),
None => None,
};
let mut last = s3.map(|s| s.2);
// handle elif:
for i in s2.into_iter().rev() {
@@ -346,35 +328,30 @@ IfStatement: ast::LocatedStatement = {
ast::LocatedStatement {
location: loc,
node: ast::Statement::If { test: t, body: s1, orelse: last }
node: ast::Statement::If { test, body: s1, orelse: last }
}
},
};
WhileStatement: ast::LocatedStatement = {
<loc:@L> "while" <e:Test> ":" <s:Suite> <s2:("else" ":" Suite)?> => {
let or_else = match s2 {
Some(s) => Some(s.2),
None => None,
};
<loc:@L> "while" <test:Test> ":" <body:Suite> <s2:("else" ":" Suite)?> => {
let or_else = s2.map(|s| s.2);
ast::LocatedStatement {
location: loc,
node: ast::Statement::While { test: e, body: s, orelse: or_else },
node: ast::Statement::While { test, body, orelse: or_else },
}
},
};
ForStatement: ast::LocatedStatement = {
<loc:@L> "for" <e:ExpressionList> "in" <t:TestList> ":" <s:Suite> <s2:("else" ":" Suite)?> => {
let or_else = match s2 {
Some(s) => Some(s.2),
None => None,
};
<loc:@L> <is_async:"async"?> "for" <target:ExpressionList> "in" <iter:TestList> ":" <body:Suite> <s2:("else" ":" Suite)?> => {
let orelse = s2.map(|s| s.2);
ast::LocatedStatement {
location: loc,
node: ast::Statement::For {
target: e,
iter: t, body: s, orelse: or_else
node: if is_async.is_some() {
ast::Statement::AsyncFor { target, iter, body, orelse }
} else {
ast::Statement::For { target, iter, body, orelse }
},
}
},
@@ -382,14 +359,8 @@ ForStatement: ast::LocatedStatement = {
TryStatement: ast::LocatedStatement = {
<loc:@L> "try" ":" <body:Suite> <handlers:ExceptClause*> <else_suite:("else" ":" Suite)?> <finally:("finally" ":" Suite)?> => {
let or_else = match else_suite {
Some(s) => Some(s.2),
None => None,
};
let finalbody = match finally {
Some(s) => Some(s.2),
None => None,
};
let or_else = else_suite.map(|s| s.2);
let finalbody = finally.map(|s| s.2);
ast::LocatedStatement {
location: loc,
node: ast::Statement::Try {
@@ -430,59 +401,59 @@ WithStatement: ast::LocatedStatement = {
WithItem: ast::WithItem = {
<t:Test> <n:("as" Expression)?> => {
let optional_vars = match n {
Some(val) => Some(val.1),
None => None,
};
let optional_vars = n.map(|val| val.1);
ast::WithItem { context_expr: t, optional_vars }
},
};
FuncDef: ast::LocatedStatement = {
<d:Decorator*> <loc:@L> "def" <i:Identifier> <a:Parameters> ":" <s:Suite> => {
<d:Decorator*> <loc:@L> <is_async:"async"?> "def" <i:Identifier> <a:Parameters> <r:("->" Test)?> ":" <s:Suite> => {
ast::LocatedStatement {
location: loc,
node: ast::Statement::FunctionDef {
name: i,
args: a,
body: s,
decorator_list: d,
}
node: if is_async.is_some() {
ast::Statement::AsyncFunctionDef {
name: i,
args: a,
body: s,
decorator_list: d,
returns: r.map(|x| x.1),
}
} else {
ast::Statement::FunctionDef {
name: i,
args: a,
body: s,
decorator_list: d,
returns: r.map(|x| x.1),
}
}
}
},
};
Parameters: ast::Parameters = {
"(" <a: (TypedArgsList)?> ")" => {
match a {
Some(a) => a,
None => Default::default(),
}
},
"(" <a: (ParameterList<TypedParameter>)?> ")" => a.unwrap_or_else(Default::default),
};
// parameters are (String, None), kwargs are (String, Some(Test)) where Test is
// the default
TypedArgsList: ast::Parameters = {
<param1:TypedParameters> <args2:("," ParameterListStarArgs)?> => {
// Note that this is a macro which is used once for function defs, and
// once for lambda defs.
ParameterList<ArgType>: ast::Parameters = {
<param1:ParameterDefs<ArgType>> <args2:("," ParameterListStarArgs<ArgType>)?> ","? => {
let (names, default_elements) = param1;
// Now gather rest of parameters:
let (vararg, kwonlyargs, kw_defaults, kwarg) = match args2 {
Some((_, x)) => x,
None => (None, vec![], vec![], None),
};
let (vararg, kwonlyargs, kw_defaults, kwarg) = args2.map_or((None, vec![], vec![], None), |x| x.1);
ast::Parameters {
args: names,
kwonlyargs: kwonlyargs,
vararg: vararg,
kwarg: kwarg,
vararg: vararg.into(),
kwarg: kwarg.into(),
defaults: default_elements,
kw_defaults: kw_defaults,
}
},
<param1:TypedParameters> <kw:("," KwargParameter)> => {
<param1:ParameterDefs<ArgType>> <kw:("," KwargParameter<ArgType>)> ","? => {
let (names, default_elements) = param1;
// Now gather rest of parameters:
@@ -494,29 +465,29 @@ TypedArgsList: ast::Parameters = {
ast::Parameters {
args: names,
kwonlyargs: kwonlyargs,
vararg: vararg,
kwarg: kwarg,
vararg: vararg.into(),
kwarg: kwarg.into(),
defaults: default_elements,
kw_defaults: kw_defaults,
}
},
<params:ParameterListStarArgs> => {
<params:ParameterListStarArgs<ArgType>> ","? => {
let (vararg, kwonlyargs, kw_defaults, kwarg) = params;
ast::Parameters {
args: vec![],
kwonlyargs: kwonlyargs,
vararg: vararg,
kwarg: kwarg,
vararg: vararg.into(),
kwarg: kwarg.into(),
defaults: vec![],
kw_defaults: kw_defaults,
}
},
<kw:KwargParameter> => {
<kw:KwargParameter<ArgType>> ","? => {
ast::Parameters {
args: vec![],
kwonlyargs: vec![],
vararg: None,
kwarg: Some(kw),
vararg: ast::Varargs::None,
kwarg: Some(kw).into(),
defaults: vec![],
kw_defaults: vec![],
}
@@ -525,8 +496,8 @@ TypedArgsList: ast::Parameters = {
// Use inline here to make sure the "," is not creating an ambiguity.
#[inline]
TypedParameters: (Vec<String>, Vec<ast::Expression>) = {
<param1:TypedParameterDef> <param2:("," TypedParameterDef)*> => {
ParameterDefs<ArgType>: (Vec<ast::Parameter>, Vec<ast::Expression>) = {
<param1:ParameterDef<ArgType>> <param2:("," ParameterDef<ArgType>)*> => {
// Combine first parameters:
let mut args = vec![param1];
args.extend(param2.into_iter().map(|x| x.1));
@@ -535,7 +506,6 @@ TypedParameters: (Vec<String>, Vec<ast::Expression>) = {
let mut default_elements = vec![];
for (name, default) in args.into_iter() {
names.push(name.clone());
if let Some(default) = default {
default_elements.push(default);
} else {
@@ -544,28 +514,38 @@ TypedParameters: (Vec<String>, Vec<ast::Expression>) = {
// have defaults
panic!(
"non-default argument follows default argument: {}",
name
&name.arg
);
}
}
names.push(name);
}
(names, default_elements)
}
};
TypedParameterDef: (String, Option<ast::Expression>) = {
<i:TypedParameter> => (i, None),
<i:TypedParameter> "=" <e:Test> => (i, Some(e)),
ParameterDef<ArgType>: (ast::Parameter, Option<ast::Expression>) = {
<i:ArgType> => (i, None),
<i:ArgType> "=" <e:Test> => (i, Some(e)),
};
// TODO: add type annotations here:
TypedParameter: String = {
Identifier,
UntypedParameter: ast::Parameter = {
<i:Identifier> => ast::Parameter { arg: i, annotation: None },
};
ParameterListStarArgs: (Option<Option<String>>, Vec<String>, Vec<Option<ast::Expression>>, Option<Option<String>>) = {
"*" <va:Identifier?> <kw:("," TypedParameterDef)*> <kwarg:("," KwargParameter)?> => {
TypedParameter: ast::Parameter = {
<arg:Identifier> <a:(":" Test)?>=> {
let annotation = a.map(|x| Box::new(x.1));
ast::Parameter { arg, annotation }
},
};
// Use inline here to make sure the "," is not creating an ambiguity.
// TODO: figure out another grammar that makes this inline no longer required.
#[inline]
ParameterListStarArgs<ArgType>: (Option<Option<ast::Parameter>>, Vec<ast::Parameter>, Vec<Option<ast::Expression>>, Option<Option<ast::Parameter>>) = {
"*" <va:ArgType?> <kw:("," ParameterDef<ArgType>)*> <kwarg:("," KwargParameter<ArgType>)?> => {
// Extract keyword arguments:
let mut kwonlyargs = vec![];
let mut kw_defaults = vec![];
@@ -574,17 +554,14 @@ ParameterListStarArgs: (Option<Option<String>>, Vec<String>, Vec<Option<ast::Exp
kw_defaults.push(value);
}
let kwarg = match kwarg {
Some((_, name)) => Some(name),
None => None,
};
let kwarg = kwarg.map(|n| n.1);
(Some(va), kwonlyargs, kw_defaults, kwarg)
}
};
KwargParameter: Option<String> = {
"**" <kwarg:Identifier?> => {
KwargParameter<ArgType>: Option<ast::Parameter> = {
"**" <kwarg:ArgType?> => {
kwarg
}
};
@@ -608,82 +585,84 @@ ClassDef: ast::LocatedStatement = {
},
};
Path: ast::Expression = {
<n:Identifier> => ast::Expression::Identifier { name: n },
<p:Path> "." <n:name> => {
ast::Expression::Attribute {
value: Box::new(p),
name: n,
}
},
};
// Decorators:
Decorator: ast::Expression = {
"@" <n:DottedName> <a: ("(" ArgumentList ")")?> "\n" => {
let name = ast::Expression::Identifier { name: n };
"@" <p:Path> <a: ("(" ArgumentList ")")?> "\n" => {
match a {
Some((_, args, _)) => ast::Expression::Call {
function: Box::new(name),
function: Box::new(p),
args: args.0,
keywords: args.1,
},
None => name,
None => p,
}
},
};
YieldExpr: ast::Expression = {
"yield" <ex:TestList?> => {
ast::Expression::Yield {
value: ex.map(|expr| Box::new(
if expr.len() > 1 {
ast::Expression::Tuple { elements: expr }
} else {
expr.into_iter().next().unwrap()
})
)
}
},
"yield" "from" <e:Test> => {
ast::Expression::YieldFrom {
value: Box::new(e),
}
},
"yield" <value:TestList?> => ast::Expression::Yield { value: value.map(Box::new) },
"yield" "from" <e:Test> => ast::Expression::YieldFrom { value: Box::new(e) },
};
Test: ast::Expression = {
<e:OrTest> <c: ("if" OrTest "else" Test)?> => {
match c {
Some(c) => {
ast::Expression::IfExpression {
test: Box::new(c.1),
body: Box::new(e),
orelse: Box::new(c.3),
}
},
None => e,
<expr:OrTest> <condition: ("if" OrTest "else" Test)?> => {
if let Some(c) = condition {
ast::Expression::IfExpression {
test: Box::new(c.1),
body: Box::new(expr),
orelse: Box::new(c.3),
}
} else {
expr
}
},
<e:LambdaDef> => e,
LambdaDef,
};
LambdaDef: ast::Expression = {
"lambda" <p:TypedArgsList?> ":" <b:Expression> =>
"lambda" <p:ParameterList<UntypedParameter>?> ":" <body:Test> =>
ast::Expression::Lambda {
args: p.unwrap_or(Default::default()),
body:Box::new(b)
body: Box::new(body)
}
}
OrTest: ast::Expression = {
<e:AndTest> => e,
AndTest,
<e1:OrTest> "or" <e2:AndTest> => ast::Expression::BoolOp { a: Box::new(e1), op: ast::BooleanOperator::Or, b: Box::new(e2) },
};
AndTest: ast::Expression = {
<e:NotTest> => e,
NotTest,
<e1:AndTest> "and" <e2:NotTest> => ast::Expression::BoolOp { a: Box::new(e1), op: ast::BooleanOperator::And, b: Box::new(e2) },
};
NotTest: ast::Expression = {
"not" <e:NotTest> => ast::Expression::Unop { a: Box::new(e), op: ast::UnaryOperator::Not },
<e:Comparison> => e,
Comparison,
};
Comparison: ast::Expression = {
<e1:Comparison> <op:CompOp> <e2:Expression> => ast::Expression::Compare { a: Box::new(e1), op: op, b: Box::new(e2) },
<e:Expression> => e,
<e:Expression> <comparisons:(CompOp Expression)+> => {
let mut vals = vec![e];
let mut ops = vec![];
for x in comparisons {
ops.push(x.0);
vals.push(x.1);
}
ast::Expression::Compare { vals, ops }
},
Expression,
};
CompOp: ast::Comparison = {
@@ -701,7 +680,7 @@ CompOp: ast::Comparison = {
Expression: ast::Expression = {
<e1:Expression> "|" <e2:XorExpression> => ast::Expression::Binop { a: Box::new(e1), op: ast::Operator::BitOr, b: Box::new(e2) },
<e:XorExpression> => e,
XorExpression,
};
XorExpression: ast::Expression = {
@@ -751,7 +730,7 @@ Factor: ast::Expression = {
"+" <e:Factor> => ast::Expression::Unop { a: Box::new(e), op: ast::UnaryOperator::Pos },
"-" <e:Factor> => ast::Expression::Unop { a: Box::new(e), op: ast::UnaryOperator::Neg },
"~" <e:Factor> => ast::Expression::Unop { a: Box::new(e), op: ast::UnaryOperator::Inv },
<e:Power> => e,
Power,
};
Power: ast::Expression = {
@@ -764,14 +743,38 @@ Power: ast::Expression = {
};
AtomExpr: ast::Expression = {
<e:Atom> => e,
<f:AtomExpr> "(" <a:ArgumentList> ")" => ast::Expression::Call { function: Box::new(f), args: a.0, keywords: a.1 },
<e:AtomExpr> "[" <s:Subscript> "]" => ast::Expression::Subscript { a: Box::new(e), b: Box::new(s) },
<e:AtomExpr> "." <n:Identifier> => ast::Expression::Attribute { value: Box::new(e), name: n },
<is_await:"await"?> <atom:AtomExpr2> => {
if is_await.is_some() {
ast::Expression::Await { value: Box::new(atom) }
} else {
atom
}
}
}
AtomExpr2: ast::Expression = {
Atom,
<f:AtomExpr2> "(" <a:ArgumentList> ")" => ast::Expression::Call { function: Box::new(f), args: a.0, keywords: a.1 },
<e:AtomExpr2> "[" <s:SubscriptList> "]" => ast::Expression::Subscript { a: Box::new(e), b: Box::new(s) },
<e:AtomExpr2> "." <n:Identifier> => ast::Expression::Attribute { value: Box::new(e), name: n },
};
SubscriptList: ast::Expression = {
<s1:Subscript> <s2:("," Subscript)*> ","? => {
if s2.is_empty() {
s1
} else {
let mut dims = vec![s1];
for x in s2 {
dims.push(x.1)
}
ast::Expression::Tuple { elements: dims }
}
}
};
Subscript: ast::Expression = {
<e:Test> => e,
Test,
<e1:Test?> ":" <e2:Test?> <e3:SliceOp?> => {
let s1 = e1.unwrap_or(ast::Expression::None);
let s2 = e2.unwrap_or(ast::Expression::None);
@@ -785,29 +788,17 @@ SliceOp: ast::Expression = {
}
Atom: ast::Expression = {
StringConstant,
<n:Number> => ast::Expression::Number { value: n },
<i:Identifier> => ast::Expression::Identifier { name: i },
<value:StringGroup> => ast::Expression::String { value },
<value:Bytes> => ast::Expression::Bytes { value },
<value:Number> => ast::Expression::Number { value },
<name:Identifier> => ast::Expression::Identifier { name },
"[" <e:TestListComp?> "]" => {
let elements = e.unwrap_or(Vec::new());
ast::Expression::List { elements }
},
"[" <e:TestListComp2> "]" => {
// List comprehension:
e
},
"(" <e:TestList?> <trailing_comma:","?> ")" => {
match e {
None => ast::Expression::Tuple { elements: Vec::new() },
Some(elements) => {
if elements.len() == 1 && trailing_comma.is_none() {
// This is "(e)", which is equivalent to "e"
elements.into_iter().next().unwrap()
} else {
ast::Expression::Tuple { elements }
}
}
}
"[" <e:TestListComp2> "]" => e,
"(" <elements:TestList?> ")" => {
elements.unwrap_or(ast::Expression::Tuple { elements: Vec::new() })
},
"(" <e:Test> <c:CompFor> ")" => {
ast::Expression::Comprehension {
@@ -822,12 +813,11 @@ Atom: ast::Expression = {
"True" => ast::Expression::True,
"False" => ast::Expression::False,
"None" => ast::Expression::None,
"..." => ast::Expression::Ellipsis,
};
TestListComp: Vec<ast::Expression> = {
<e:OneOrMore<TestOrStarExpr>> <_trailing_comma:","?> => {
e
},
<e:OneOrMore<TestOrStarExpr>> <_trailing_comma:","?> => e,
};
TestListComp2: ast::Expression = {
@@ -839,10 +829,8 @@ TestListComp2: ast::Expression = {
},
};
TestDict: Vec<(ast::Expression, ast::Expression)> = {
<e1:OneOrMore<DictEntry>> <_trailing_comma:","?> => {
e1
}
TestDict: Vec<(Option<ast::Expression>, ast::Expression)> = {
<elements:OneOrMore<DictElement>> <_trailing_comma:","?> => elements,
};
TestDictComp: ast::Expression = {
@@ -858,10 +846,13 @@ DictEntry: (ast::Expression, ast::Expression) = {
<e1: Test> ":" <e2: Test> => (e1, e2),
};
DictElement: (Option<ast::Expression>, ast::Expression) = {
<e:DictEntry> => (Some(e.0), e.1),
"**" <e:Expression> => (None, e),
};
TestSet: Vec<ast::Expression> = {
<e1:OneOrMore<Test>> ","? => {
e1
}
<e1:OneOrMore<Test>> ","? => e1
};
TestSetComp: ast::Expression = {
@@ -873,31 +864,37 @@ TestSetComp: ast::Expression = {
}
};
ExpressionOrStarExpression = {
Expression,
StarExpr
};
ExpressionList: ast::Expression = {
<e: ExpressionList2> => {
if e.len() == 1 {
e.into_iter().next().unwrap()
<elements: OneOrMore<ExpressionOrStarExpression>> <trailing_comma:","?> => {
if elements.len() == 1 && trailing_comma.is_none() {
elements.into_iter().next().unwrap()
} else {
ast::Expression::Tuple { elements: e }
ast::Expression::Tuple { elements }
}
},
};
ExpressionList2: Vec<ast::Expression> = {
<e1:Expression> <e2:("," Expression)*> ","? => {
let mut l = vec![e1];
l.extend(e2.into_iter().map(|x| x.1));
l
},
<elements:OneOrMore<Expression>> ","? => elements,
};
#[inline]
TestList: Vec<ast::Expression> = {
<e1:Test> <e2: ("," Test)*> => {
let mut l = vec![e1];
l.extend(e2.into_iter().map(|x| x.1));
l
}
// A test list is one of:
// - a list of expressions
// - a single expression
// - a single expression followed by a trailing comma
TestList: ast::Expression = {
<elements:OneOrMore<Test>> <trailing_comma: ","?> => {
if elements.len() == 1 && trailing_comma.is_none() {
elements.into_iter().next().unwrap()
} else {
ast::Expression::Tuple { elements }
}
}
};
// Test
@@ -906,27 +903,16 @@ StarExpr: ast::Expression = {
};
// Comprehensions:
CompFor: Vec<ast::Comprehension> = {
<c:SingleForComprehension+> => c,
};
CompFor: Vec<ast::Comprehension> = <c:SingleForComprehension+> => c;
SingleForComprehension: ast::Comprehension = {
"for" <e:ExpressionList> "in" <i:OrTest> <c2:ComprehensionIf*> => {
ast::Comprehension {
target: e,
iter: i,
ifs: c2,
}
"for" <target:ExpressionList> "in" <iter:OrTest> <c2:ComprehensionIf*> => {
ast::Comprehension { target, iter, ifs: c2 }
}
};
ExpressionNoCond: ast::Expression = {
OrTest,
};
ComprehensionIf: ast::Expression = {
"if" <c:ExpressionNoCond> => c,
};
ExpressionNoCond: ast::Expression = OrTest;
ComprehensionIf: ast::Expression = "if" <c:ExpressionNoCond> => c;
ArgumentList: (Vec<ast::Expression>, Vec<ast::Keyword>) = {
<e: Comma<FunctionArgument>> => {
@@ -938,8 +924,15 @@ ArgumentList: (Vec<ast::Expression>, Vec<ast::Keyword>) = {
keywords.push(ast::Keyword { name: n, value: value });
},
None => {
if keywords.len() > 0 {
panic!("positional argument follows keyword argument");
// Allow starred args after keyword arguments.
let is_starred = if let ast::Expression::Starred { .. } = &value {
true
} else {
false
};
if keywords.len() > 0 && !is_starred {
panic!("positional argument follows keyword argument {:?}", keywords);
};
args.push(value);
},
@@ -983,19 +976,33 @@ OneOrMore<T>: Vec<T> = {
};
Number: ast::Number = {
<s:int> => { ast::Number::Integer { value: s } },
<s:float> => { ast::Number::Float { value: s } },
<value:int> => { ast::Number::Integer { value } },
<value:float> => { ast::Number::Float { value } },
<s:complex> => { ast::Number::Complex { real: s.0, imag: s.1 } },
};
StringConstant: ast::Expression = {
<s:string+> => {
let glued = s.join("");
ast::Expression::String { value: glued }
StringGroup: ast::StringGroup = {
<s:string+> =>? {
let mut values = vec![];
for (value, is_fstring) in s {
values.push(if is_fstring {
parse_fstring(&value)?
} else {
ast::StringGroup::Constant { value }
})
}
Ok(if values.len() > 1 {
ast::StringGroup::Joined { values }
} else {
values.into_iter().next().unwrap()
})
},
};
Bytes: Vec<u8> = {
<s:bytes+> => {
let glued = s.into_iter().flatten().collect::<Vec<u8>>();
ast::Expression::Bytes { value: glued }
s.into_iter().flatten().collect::<Vec<u8>>()
},
};
@@ -1017,6 +1024,7 @@ extern {
"~" => lexer::Tok::Tilde,
":" => lexer::Tok::Colon,
"." => lexer::Tok::Dot,
"..." => lexer::Tok::Ellipsis,
"," => lexer::Tok::Comma,
"*" => lexer::Tok::Star,
"**" => lexer::Tok::DoubleStar,
@@ -1055,9 +1063,12 @@ extern {
"<=" => lexer::Tok::LessEqual,
">" => lexer::Tok::Greater,
">=" => lexer::Tok::GreaterEqual,
"->" => lexer::Tok::Rarrow,
"and" => lexer::Tok::And,
"as" => lexer::Tok::As,
"assert" => lexer::Tok::Assert,
"async" => lexer::Tok::Async,
"await" => lexer::Tok::Await,
"break" => lexer::Tok::Break,
"class" => lexer::Tok::Class,
"continue" => lexer::Tok::Continue,
@@ -1092,7 +1103,7 @@ extern {
int => lexer::Tok::Int { value: <BigInt> },
float => lexer::Tok::Float { value: <f64> },
complex => lexer::Tok::Complex { real: <f64>, imag: <f64> },
string => lexer::Tok::String { value: <String> },
string => lexer::Tok::String { value: <String>, is_fstring: <bool> },
bytes => lexer::Tok::Bytes { value: <Vec<u8>> },
name => lexer::Tok::Name { name: <String> },
"\n" => lexer::Tok::Newline,

View File

@@ -3,13 +3,13 @@
use num_bigint::BigInt;
/// Python source code can be tokenized in a sequence of these tokens.
#[derive(Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
pub enum Tok {
Name { name: String },
Int { value: BigInt },
Float { value: f64 },
Complex { real: f64, imag: f64 },
String { value: String },
String { value: String, is_fstring: bool },
Bytes { value: Vec<u8> },
Newline,
Indent,
@@ -17,6 +17,7 @@ pub enum Tok {
StartProgram,
StartStatement,
StartExpression,
EndOfFile,
Lpar,
Rpar,
Lsqb,
@@ -72,6 +73,8 @@ pub enum Tok {
And,
As,
Assert,
Async,
Await,
Break,
Class,
Continue,

View File

@@ -2,6 +2,7 @@
name = "py_code_object"
version = "0.1.0"
authors = ["Shing Lyu <shing.lyu@gmail.com>"]
edition = "2018"
[dependencies]
log = "0.3"

View File

@@ -2,6 +2,7 @@
name = "python_compiler"
version = "0.1.0"
authors = ["Shing Lyu <shing.lyu@gmail.com>"]
edition = "2018"
[dependencies]
cpython = { git = "https://github.com/dgrunwald/rust-cpython.git" }

View File

@@ -56,7 +56,7 @@ impl VirtualMachine {
}
}
// Can we get rid of the code paramter?
// Can we get rid of the code parameter?
fn make_frame(&self, code: PyCodeObject, callargs: HashMap<String, Rc<NativeType>>, globals: Option<HashMap<String, Rc<NativeType>>>) -> Frame {
//populate the globals and locals
@@ -345,7 +345,7 @@ impl VirtualMachine {
let exception = match argc {
1 => curr_frame.stack.pop().unwrap(),
0 | 2 | 3 => panic!("Not implemented!"),
_ => panic!("Invalid paramter for RAISE_VARARGS, must be between 0 to 3")
_ => panic!("Invalid parameter for RAISE_VARARGS, must be between 0 to 3")
};
panic!("{:?}", exception);
}

1
rustfmt.toml Normal file
View File

@@ -0,0 +1 @@
edition = "2018"

View File

@@ -1,23 +1,23 @@
//extern crate rustpython_parser;
#[macro_use]
extern crate clap;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate rustpython_parser;
extern crate rustpython_vm;
extern crate rustyline;
use clap::{App, Arg};
use rustpython_parser::parser;
use rustpython_vm::obj::objstr;
use rustpython_vm::print_exception;
use rustpython_vm::pyobject::{AttributeProtocol, PyObjectRef, PyResult};
use rustpython_vm::VirtualMachine;
use rustpython_vm::{compile, import};
use rustyline::error::ReadlineError;
use rustyline::Editor;
use std::path::Path;
use rustpython_compiler::{compile, error::CompileError, error::CompileErrorType};
use rustpython_parser::error::ParseErrorType;
use rustpython_vm::{
frame::Scope,
import,
obj::objstr,
print_exception,
pyobject::{ItemProtocol, PyResult},
util, VirtualMachine,
};
use rustyline::{error::ReadlineError, Editor};
use std::path::PathBuf;
fn main() {
@@ -49,167 +49,231 @@ fn main() {
.get_matches();
// Construct vm:
let mut vm = VirtualMachine::new();
let vm = VirtualMachine::new();
let res = import::init_importlib(&vm, true);
handle_exception(&vm, res);
// Figure out if a -c option was given:
let result = if let Some(command) = matches.value_of("c") {
run_command(&mut vm, command.to_string())
run_command(&vm, command.to_string())
} else if let Some(module) = matches.value_of("m") {
run_module(&mut vm, module)
run_module(&vm, module)
} else {
// Figure out if a script was passed:
match matches.value_of("script") {
None => run_shell(&mut vm),
Some(filename) => run_script(&mut vm, &filename.to_string()),
None => run_shell(&vm),
Some(filename) => run_script(&vm, filename),
}
};
// See if any exception leaked out:
handle_exception(&mut vm, result);
handle_exception(&vm, result);
}
fn _run_string(vm: &mut VirtualMachine, source: &str, source_path: Option<String>) -> PyResult {
let code_obj = compile::compile(vm, &source.to_string(), compile::Mode::Exec, source_path)?;
fn _run_string(vm: &VirtualMachine, source: &str, source_path: String) -> PyResult {
let code_obj = vm
.compile(source, &compile::Mode::Exec, source_path.clone())
.map_err(|err| vm.new_syntax_error(&err))?;
// trace!("Code object: {:?}", code_obj.borrow());
let builtins = vm.get_builtin_scope();
let vars = vm.context().new_scope(Some(builtins)); // Keep track of local variables
vm.run_code_obj(code_obj, vars)
let attrs = vm.ctx.new_dict();
attrs.set_item("__file__", vm.new_str(source_path), vm)?;
vm.run_code_obj(code_obj, Scope::with_builtins(None, attrs, vm))
}
fn handle_exception(vm: &mut VirtualMachine, result: PyResult) {
match result {
Ok(_value) => {}
Err(err) => {
print_exception(vm, &err);
std::process::exit(1);
}
fn handle_exception(vm: &VirtualMachine, result: PyResult) {
if let Err(err) = result {
print_exception(vm, &err);
std::process::exit(1);
}
}
fn run_command(vm: &mut VirtualMachine, mut source: String) -> PyResult {
fn run_command(vm: &VirtualMachine, mut source: String) -> PyResult {
debug!("Running command {}", source);
// This works around https://github.com/RustPython/RustPython/issues/17
source.push_str("\n");
_run_string(vm, &source, None)
source.push('\n');
_run_string(vm, &source, "<stdin>".to_string())
}
fn run_module(vm: &mut VirtualMachine, module: &str) -> PyResult {
fn run_module(vm: &VirtualMachine, module: &str) -> PyResult {
debug!("Running module {}", module);
let current_path = PathBuf::from(".");
import::import_module(vm, current_path, module)
vm.import(module, &vm.ctx.new_tuple(vec![]), 0)
}
fn run_script(vm: &mut VirtualMachine, script_file: &str) -> PyResult {
fn run_script(vm: &VirtualMachine, script_file: &str) -> PyResult {
debug!("Running file {}", script_file);
// Parse an ast from it:
let filepath = Path::new(script_file);
match parser::read_file(filepath) {
Ok(source) => _run_string(vm, &source, Some(filepath.to_str().unwrap().to_string())),
Err(msg) => {
error!("Parsing went horribly wrong: {}", msg);
let file_path = PathBuf::from(script_file);
let file_path = if file_path.is_file() {
file_path
} else if file_path.is_dir() {
let main_file_path = file_path.join("__main__.py");
if main_file_path.is_file() {
main_file_path
} else {
error!(
"can't find '__main__' module in '{}'",
file_path.to_str().unwrap()
);
std::process::exit(1);
}
} else {
error!(
"can't open file '{}': No such file or directory",
file_path.to_str().unwrap()
);
std::process::exit(1);
};
let dir = file_path.parent().unwrap().to_str().unwrap().to_string();
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, &source, file_path.to_str().unwrap().to_string()),
Err(err) => {
error!(
"Failed reading file '{}': {:?}",
file_path.to_str().unwrap(),
err.kind()
);
std::process::exit(1);
}
}
}
fn shell_exec(vm: &mut VirtualMachine, source: &str, scope: PyObjectRef) -> bool {
match compile::compile(vm, &source.to_string(), compile::Mode::Single, None) {
#[test]
fn test_run_script() {
let vm = VirtualMachine::new();
// test file run
let r = run_script(&vm, "tests/snippets/dir_main/__main__.py");
assert!(r.is_ok());
// test module run
let r = run_script(&vm, "tests/snippets/dir_main");
assert!(r.is_ok());
}
fn shell_exec(vm: &VirtualMachine, source: &str, scope: Scope) -> Result<(), CompileError> {
match vm.compile(source, &compile::Mode::Single, "<stdin>".to_string()) {
Ok(code) => {
match vm.run_code_obj(code, scope) {
Ok(_value) => {
// Printed already.
match vm.run_code_obj(code, scope.clone()) {
Ok(value) => {
// Save non-None values as "_"
use rustpython_vm::pyobject::{IdProtocol, IntoPyObject};
if !value.is(&vm.get_none()) {
let key = objstr::PyString::from("_").into_pyobject(vm);
scope.globals.set_item(key, value, vm).unwrap();
}
}
Err(err) => {
print_exception(vm, &err);
}
}
Ok(())
}
// Don't inject syntax errors for line continuation
Err(
err @ CompileError {
error: CompileErrorType::Parse(ParseErrorType::EOF),
..
},
) => Err(err),
Err(err) => {
// Enum rather than special string here.
let name = vm.new_str("msg".to_string());
let msg = match vm.get_attribute(err.clone(), name) {
Ok(value) => objstr::get_value(&value),
Err(_) => panic!("Expected msg attribute on exception object!"),
};
if msg == "Unexpected end of input." {
return false;
} else {
print_exception(vm, &err);
}
let exc = vm.new_syntax_error(&err);
print_exception(vm, &exc);
Err(err)
}
};
true
}
}
fn run_shell(vm: &mut VirtualMachine) -> PyResult {
#[cfg(not(unix))]
fn get_history_path() -> PathBuf {
PathBuf::from(".repl_history.txt")
}
#[cfg(unix)]
fn get_history_path() -> PathBuf {
//work around for windows dependent builds. The xdg crate is unix specific
//so access to the BaseDirectories struct breaks builds on python.
extern crate xdg;
let xdg_dirs = xdg::BaseDirectories::with_prefix("rustpython").unwrap();
xdg_dirs.place_cache_file("repl_history.txt").unwrap()
}
fn get_prompt(vm: &VirtualMachine, prompt_name: &str) -> String {
vm.get_attribute(vm.sys_module.clone(), prompt_name)
.ok()
.as_ref()
.map(objstr::get_value)
.unwrap_or_else(String::new)
}
fn run_shell(vm: &VirtualMachine) -> PyResult {
println!(
"Welcome to the magnificent Rust Python {} interpreter",
"Welcome to the magnificent Rust Python {} interpreter \u{1f631} \u{1f596}",
crate_version!()
);
let builtins = vm.get_builtin_scope();
let vars = vm.context().new_scope(Some(builtins)); // Keep track of local variables
let vars = vm.new_scope_with_builtins();
// Read a single line:
let mut input = String::new();
let mut rl = Editor::<()>::new();
let mut repl = Editor::<()>::new();
// TODO: Store the history in a proper XDG directory
let repl_history_path = ".repl_history.txt";
if rl.load_history(repl_history_path).is_err() {
// Retrieve a `history_path_str` dependent on the OS
let repl_history_path_str = &get_history_path();
if repl.load_history(repl_history_path_str).is_err() {
println!("No previous history.");
}
let mut continuing = false;
loop {
// TODO: modules dont support getattr / setattr yet
//let prompt = match vm.get_attribute(vm.sys_module.clone(), "ps1") {
// Ok(value) => objstr::get_value(&value),
// Err(_) => ">>>>> ".to_string(),
//};
// We can customize the prompt:
let ps1 = objstr::get_value(&vm.sys_module.get_attr("ps1").unwrap());
let ps2 = objstr::get_value(&vm.sys_module.get_attr("ps2").unwrap());
match rl.readline(&ps1) {
let prompt = if continuing {
get_prompt(vm, "ps2")
} else {
get_prompt(vm, "ps1")
};
match repl.readline(&prompt) {
Ok(line) => {
debug!("You entered {:?}", line);
input.push_str(&line);
input.push_str("\n");
input.push('\n');
repl.add_history_entry(line.trim_end());
debug!("You entered {:?}", input);
if shell_exec(vm, &input, vars.clone()) {
// Line was complete.
rl.add_history_entry(input.trim_right().as_ref());
input = String::new();
} else {
loop {
// until an empty line is pressed AND the code is complete
//let prompt = match vm.get_attribute(vm.sys_module.clone(), "ps2") {
// Ok(value) => objstr::get_value(&value),
// Err(_) => "..... ".to_string(),
//};
match rl.readline(&ps2) {
Ok(line) => {
if line.len() == 0 {
if shell_exec(vm, &input, vars.clone()) {
rl.add_history_entry(input.trim_right().as_ref());
input = String::new();
break;
}
} else {
input.push_str(&line);
input.push_str("\n");
}
}
Err(msg) => panic!("Error: {:?}", msg),
}
if continuing {
if line.is_empty() {
continuing = false;
} else {
continue;
}
}
match shell_exec(vm, &input, vars.clone()) {
Err(CompileError {
error: CompileErrorType::Parse(ParseErrorType::EOF),
..
}) => {
continuing = true;
continue;
}
_ => {
input = String::new();
}
}
}
Err(ReadlineError::Interrupted) => {
// TODO: Raise a real KeyboardInterrupt exception
println!("^C");
break;
continuing = false;
continue;
}
Err(ReadlineError::Eof) => {
break;
@@ -220,7 +284,7 @@ fn run_shell(vm: &mut VirtualMachine) -> PyResult {
}
};
}
rl.save_history(repl_history_path).unwrap();
repl.save_history(repl_history_path_str).unwrap();
Ok(vm.get_none())
}

1
tests/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
snippets/whats_left_*.py

View File

@@ -10,7 +10,33 @@ pip install pipenv
(cd tests; pipenv install)
# Build outside of the test runner
cargo build --verbose --release
if [ $CODE_COVERAGE = "true" ]
then
find . -name '*.gcda' -delete
find . -name '*.gcno' -delete
export CARGO_INCREMENTAL=0
export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Zno-landing-pads"
cargo build --verbose
else
cargo build --verbose --release
fi
# Run the tests
(cd tests; pipenv run pytest)
if [ $CODE_COVERAGE = "true" ]
then
cargo test --verbose --all
zip -0 ccov.zip `find . \( -name "rustpython*.gc*" \) -print`
# Install grcov
curl -L https://github.com/mozilla/grcov/releases/download/v0.4.2/grcov-linux-x86_64.tar.bz2 | tar jxf -
./grcov ccov.zip -s . -t lcov --llvm --branch --ignore-not-existing --ignore-dir "/*" -p "x" > lcov.info
# Install codecov.io reporter
curl -s https://codecov.io/bash -o codecov.sh
bash codecov.sh -f lcov.info
fi

View File

@@ -10,4 +10,4 @@ pytest = "*"
[dev-packages]
[requires]
python_version = "3"
python_version = "3.6"

99
tests/Pipfile.lock generated
View File

@@ -1,11 +1,11 @@
{
"_meta": {
"hash": {
"sha256": "b2d2d68e7d4330ff8d889816c56b9cee4bf54962c86b2c11382108176a201ec8"
"sha256": "ce98de5914393363a8cb86a4753b3964caa53a4659a403a3ef357e2086363ef7"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3"
"python_version": "3.6"
},
"sources": [
{
@@ -16,74 +16,99 @@
]
},
"default": {
"aenum": {
"hashes": [
"sha256:3df9b84cce5dc9ed77c337079f97b66c44c0053eb87d6f4d46b888dc45801e38",
"sha256:7a77c205c4bc9d7fe9bd73b3193002d724aebf5909fa0d297534208953891ec8",
"sha256:a3208e4b28db3a7b232ff69b934aef2ea1bf27286d9978e1e597d46f490e4687"
],
"version": "==2.1.2"
},
"atomicwrites": {
"hashes": [
"sha256:240831ea22da9ab882b551b31d4225591e5e447a68c5e188db5b89ca1d487585",
"sha256:a24da68318b08ac9c9c45029f4a10371ab5b20e4226738e150e6e7c571630ae6"
"sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4",
"sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"
],
"version": "==1.1.5"
"version": "==1.3.0"
},
"attrs": {
"hashes": [
"sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265",
"sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b"
"sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79",
"sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399"
],
"version": "==18.1.0"
"version": "==19.1.0"
},
"bytecode": {
"hashes": [
"sha256:cc6931151c7f0a542f8cf7619fe1639af3b9529c4678860fa3239397cb0f7de0",
"sha256:e464004d4a9eeeca987cb4950dba11b827964b6c90cd331c1f20abd2dab3c962"
"sha256:68b1d591c7af0e5c5273e028d3cc0299fbe374dff0cf9149ec7e569be0c573e7",
"sha256:c43d5052cbff076bfdf5b0b93ff6c76e461aab628ce47d30637bb200b6b7bb2c"
],
"index": "pypi",
"version": "==0.7.0"
"version": "==0.8.0"
},
"importlib-metadata": {
"hashes": [
"sha256:6dfd58dfe281e8d240937776065dd3624ad5469c835248219bd16cf2e12dbeb7",
"sha256:cb6ee23b46173539939964df59d3d72c3e0c1b5d54b84f1d8a7e912fe43612db"
],
"version": "==0.18"
},
"more-itertools": {
"hashes": [
"sha256:c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092",
"sha256:c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e",
"sha256:fcbfeaea0be121980e15bc97b3817b5202ca73d0eae185b4550cbfce2a3ebb3d"
"sha256:2112d2ca570bb7c3e53ea1a35cd5df42bb0fd10c45f0fb97178679c3c03d64c7",
"sha256:c3e4748ba1aad8dba30a4886b0b1a2004f9a863837b8654e7059eebf727afa5a"
],
"version": "==4.3.0"
"markers": "python_version > '2.7'",
"version": "==7.0.0"
},
"packaging": {
"hashes": [
"sha256:0c98a5d0be38ed775798ece1b9727178c4469d9c3b4ada66e8e6b7849f8732af",
"sha256:9e1cbf8c12b1f1ce0bb5344b8d7ecf66a6f8a6e91bcb0c84593ed6d3ab5c4ab3"
],
"version": "==19.0"
},
"pluggy": {
"hashes": [
"sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1",
"sha256:95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1"
"sha256:0825a152ac059776623854c1543d65a4ad408eb3d33ee114dff91e57ec6ae6fc",
"sha256:b9817417e95936bf75d85d3f8767f7df6cdde751fc40aed3bb3074cbcb77757c"
],
"markers": "python_version != '3.3.*' and python_version != '3.0.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.2.*'",
"version": "==0.7.1"
"version": "==0.12.0"
},
"py": {
"hashes": [
"sha256:3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7",
"sha256:e31fb2767eb657cbde86c454f02e99cb846d3cd9d61b318525140214fdc0e98e"
"sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa",
"sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"
],
"markers": "python_version != '3.3.*' and python_version != '3.0.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.2.*'",
"version": "==1.5.4"
"version": "==1.8.0"
},
"pyparsing": {
"hashes": [
"sha256:1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a",
"sha256:9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03"
],
"version": "==2.4.0"
},
"pytest": {
"hashes": [
"sha256:86a8dbf407e437351cef4dba46736e9c5a6e3c3ac71b2e942209748e76ff2086",
"sha256:e74466e97ac14582a8188ff4c53e6cc3810315f342f6096899332ae864c1d432"
"sha256:4a784f1d4f2ef198fe9b7aef793e9fa1a3b2f84e822d9b3a64a181293a572d45",
"sha256:926855726d8ae8371803f7b2e6ec0a69953d9c6311fa7c3b6c1b929ff92d27da"
],
"index": "pypi",
"version": "==3.7.1"
"version": "==4.6.3"
},
"six": {
"hashes": [
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
"sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
"sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
],
"version": "==1.11.0"
"version": "==1.12.0"
},
"wcwidth": {
"hashes": [
"sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e",
"sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"
],
"version": "==0.1.7"
},
"zipp": {
"hashes": [
"sha256:8c1019c6aad13642199fbe458275ad6a84907634cc9f0989877ccc4a2840139d",
"sha256:ca943a7e809cc12257001ccfb99e3563da9af99d52f261725e96dfe0f9275bc3"
],
"version": "==0.5.1"
}
},
"develop": {}

View File

@@ -1,4 +1,3 @@
# Test snippets
This directory contains two sets of test snippets which can be run in
@@ -6,6 +5,10 @@ Python. The `snippets/` directory contains functional tests, and the
`benchmarks/` directory contains snippets for use in benchmarking
RustPython's performance.
## Generates the test for not implemented methods
run using cpython not_impl_gen.py it automatically generate a
test snippet to check not yet implemented methods
## Running with CPython + RustPython
@@ -15,4 +18,3 @@ compilation to bytecode. When this is done, run the bytecode with rustpython.
## Running with RustPython
The other option is to run all snippets with RustPython.

Some files were not shown because too many files have changed in this diff Show More