Git Product home page Git Product logo

arepl-electron's People

Contributors

almenon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

arepl-electron's Issues

Easy printing

When using AREPL I frequently do wrap expressions in print statements to see the value of them. Instead of doing this it would be nice if there was a shortcut that would automatically evaluate the expression and print it. For example, in FoxDot you do control-enter to evaluate the line and print the output to the console.

I could extend this idea even further. Wrapping a line that ends in a . with print(dir()) could act as a primitive form of intellisense. Or maybe doing alt-enter could wrap the line in help().

auto-download of update

Add new submenu item for auto-download of update. Change old submenu item to "release notes". Old submenu item should link back to the releases page for release notes. If you have time use the releaseNotes returned by auto-updater to show it locally.

jsonpickle.decode exhibits different behavior in AREPL than in Pycharm

In AREPL json.decode fails to decode a simple pickled enum. In Pycharm the decoding happens without any error. The reason behind this is that AREPL uses exec to execute the user's code. In the example below you can see the exact same code that works outside of exec() fails inside exec().

from enum import Enum
from jsonpickle import encode, decode


class C(Enum):
    VALUE = 1

my_list_encode = encode(C.VALUE)
decode(my_list_encode) # no error

execCode = """ # exact same code as above follows!
from enum import Enum
from jsonpickle import encode, decode


class C(Enum):
    VALUE = 1

my_list_encode = encode(C.VALUE)
decode(my_list_encode)
"""

execLocals = {}
exec(execCode,execLocals) # error!

Traceback (most recent call last):
File "C:/dev/random python scripts/misc.py", line 24, in
exec(execCode,execLocals)
File "", line 10, in
File "C:\dev\AREPL\src\python\jsonpickle_init_.py", line 152, in decode
return unpickler.decode(string, backend=backend, keys=keys)
File "C:\dev\AREPL\src\python\jsonpickle\unpickler.py", line 27, in decode
return context.restore(backend.decode(string), reset=reset)
File "C:\dev\AREPL\src\python\jsonpickle\unpickler.py", line 120, in restore
value = self._restore(obj)
File "C:\dev\AREPL\src\python\jsonpickle\unpickler.py", line 162, in _restore
return restore(obj)
File "C:\dev\AREPL\src\python\jsonpickle\unpickler.py", line 183, in _restore_reduce
if f == tags.NEWOBJ or f.__name__ == '__newobj__':
AttributeError: 'dict' object has no attribute '__name__'
"""

Auto-update not working

There should be a menu item in the top right saying "New update availible"

There is not. ๐Ÿค”

No clue why - when I debug it works perfectly.

It would be nice if the electron javascript did some logging somewhere.

de-coupling of python result handler and html

Right now the pythonResultHandler Changes the html directly, but it should pass back the results to the app, where it could decide what to do with the results. This allows me to add in more languages as well as just being better architecture design.

NaN, Infinity, and -Infinity cause errors

Python's JSON allows NaN, Infinity, and negative Infinity.

Javascript's JSON does not ๐Ÿ‘Ž

This puts me in a bit of a pickle.

Literally, I have to make my own pickler: ๐Ÿฅ’

class customPickler(jsonpickle.pickler.Pickler):
    """
    encodes float values like inf / nan as strings to follow JSON spec while keeping meaning
    Im doing this in custom class because handlers do not fire for floats
    """
    inf = float('inf')
    negativeInf = float('-inf')

    def _get_flattener(self, obj):
        if type(obj) == type(float()):
            if obj == self.inf:
                return lambda obj: 'Infinity'
            if obj == self.negativeInf:
                return lambda obj: '-Infinity'
            if isnan(obj):
                return lambda obj: 'NaN'
        return super(customPickler, self)._get_flattener(obj)

jsonpickle.pickler.Pickler = customPickler

AREPL can't print certain emojis

On a scale from 1-10, 1 being lowest, this has to be near a 1 on the severity list.

Still, it would be nice. This worked:

print(sys.stdout.encoding) # cp1252
import sys, codecs
w = codecs.getwriter('utf-8')
sys.stdout = w(sys.stdout.buffer)
import emoji
print(emoji.emojize(':eggplant:'))

but then certain accents (like รก) started printing malformed: รƒยก

I really hate encodings. Why can't everyone just talk in esperanto???

AREPL won't open on mac

Process: arepl [55016]
Path: /Users/USER/Downloads/*/arepl.app/Contents/MacOS/arepl
Identifier: com.electron.arepl
Version: ???
Code Type: X86-64 (Native)
Responsible: arepl [55016]

OS Version: Mac OS X 10.11.6 (15G1611)

Crashed Thread: 0
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000002, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY

Application Specific Information:
dyld: launch, loading dependent libraries
Dyld Error Message:
Library not loaded: @rpath/libnode.dylib
Referenced from: /Users/anon/Downloads/arepl-darwin-x64/arepl.app/Contents/Frameworks/Electron Framework.framework/Electron Framework
Reason: image not found

In mac filemenu still says "Electron"

Not sure why this is the case. I do label: require("electron").app.getName() and I have "arepl" as the name in package.json so the first item in the file menu should be arepl.

Automated unit tests for JS

If unit tests are not automated then there is a dangerous likelyhood of the dev forgetting to run them, in which case the unit tests are pointless. I already have the python unit tests automated with travis, it would be easy to run the JS tests as well.

Re-evaluation of old code is not necessary when adding code

Instead of evaluating the entire program I can pass in the old locals into eval with the section of new code. (assuming the user is adding new code, and not modifying existing code)

Every time there is a new line I would deep copy all of the old locals. For each change to the new line I would exec the new line and pass in the old locals.

This has two benefits:

  1. increased speed with larger programs

  2. No re-evaluation of old code (so repeated side-effects are avoided)

The drawback is overhead associated with deep-copying all the locals every time there is a new line. I might want to do some performance tests to see what the impact of this would be.

restart evaluation when code has changed

Python programs which display windows (through turtle / matplotlib / other libraries) run indefinitely to maintain the window. It would be nice to have the default behavior be to restart the user's python program whenever the code is changed. Then the user would not have to manually exit the window every time.

This would also be a nice solution to the infinite loop issue. Instead of having to press a hotkey to restart it would restart automatically upon change.

RecursionError when using locals

x = locals()

โš  There has been a error when trying to display your variables. Sorry :(
Traceback (most recent call last):\n File "C:\dev\AREPL\src\python\pythonEvaluator.py", line 53, in exec_input\n returnInfo['userVariables'] = jsonpickle.encode(userVariables)#, max_depth=100) # any depth above 245 resuls in error and anything above 100 takes too long to process\n File "C:\dev\AREPL\src\python\jsonpickle_init_.py", line 135, in encode\n numeric_keys=numeric_keys)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 44, in encode\n return backend.encode(context.flatten(value, reset=reset))\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 157, in flatten\n return self._flatten(obj)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 161, in _flatten\n return self._pop(self._flatten_obj(obj))\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 177, in _flatten_obj\n return flatten_func(obj)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 429, in _flatten_dict_obj\n flatten(k, v, data)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 498, in _flatten_key_value_pair\n data[k] = self._flatten(v)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 161, in _flatten\n return self._pop(self._flatten_obj(obj))\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 177, in _flatten_obj\n return flatten_func(obj)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 429, in _flatten_dict_obj\n flatten(k, v, data)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 498, in _flatten_key_value_pair\n data[k] = self._flatten(v)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 161, in _flatten\n

... a rediculous number of lines later...

return self._pop(self._flatten_obj(obj))\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 177, in _flatten_obj\n return flatten_func(obj)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 429, in _flatten_dict_obj\n flatten(k, v, data)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 481, in _flatten_key_value_pair\n if not util.is_picklable(k, v):\n File "C:\dev\AREPL\src\python\jsonpickle\util.py", line 309, in is_picklable\n return is_module_function(value) or not is_function(value)\n File "C:\dev\AREPL\src\python\jsonpickle\util.py", line 253, in is_function\n module = translate_module_name(obj.class.module)\n File "C:\dev\AREPL\src\python\jsonpickle\util.py", line 415, in translate_module_name\n if (PY3 and module == 'builtins') or module == 'exceptions':\nRecursionError: maximum recursion depth exceeded in comparison\n

Unhandled exception when creating csv reader

import csv

with open('stocks.csv') as f:
  x = csv.reader(f)

Traceback (most recent call last):\n File "C:\dev\AREPL\src\python\pythonEvaluator.py", line 53, in exec_input\n returnInfo['userVariables'] = jsonpickle.encode(userVariables)\n File "C:\dev\AREPL\src\python\jsonpickle_init_.py", line 135, in encode\n numeric_keys=numeric_keys)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 44, in encode\n return backend.encode(context.flatten(value, reset=reset))\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 157, in flatten\n return self._flatten(obj)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 161, in _flatten\n return self._pop(self._flatten_obj(obj))\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 177, in _flatten_obj\n return flatten_func(obj)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 429, in _flatten_dict_obj\n flatten(k, v, data)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 498, in _flatten_key_value_pair\n data[k] = self._flatten(v)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 161, in _flatten\n return self._pop(self._flatten_obj(obj))\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 177, in _flatten_obj\n return flatten_func(obj)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 235, in _ref_obj_instance\n return self._flatten_obj_instance(obj)\n File "C:\dev\AREPL\src\python\jsonpickle\pickler.py", line 367, in _flatten_obj_instance\n data[tags.ITERATOR] = list(map(self._flatten, islice(obj, self._max_iter)))\nValueError: I/O operation on closed file.\n

It looks like JSONpickle is failing to encode x. The JSONpickle API mentions that it can't encode file descriptors so this might be related to that. Still, I would've expected x to be encoded as None rather than an unhandled exception.

python file open error on mac

events.js:163 Uncaught Error: python: can't open file 
'Users/anon/Documents/AREPL\src\python\pythonEvaluator.py': 

[Errno 2] No such file or directory

at PythonShell.parseError (/Users/anon/Documents/AREPL/node_modules/python-shell/index.js:190)
at terminateIfNeeded (/Users/anon/Documents/AREPL/node_modules/python-shell/index.js:98)
at Socket.<anonymous> (/Users/anon/Documents/AREPL/node_modules/python-shell/index.js:78)
at emitNone (events.js:91)
at Socket.emit (events.js:188)
at endReadableNT (_stream_readable.js:975)
at _combinedTickCallback (internal/process/next_tick.js:80)
at process._tickCallback (internal/process/next_tick.js:104)

This appears to be due to extrabacon/python-shell#38

python evaluator does not start on mac

when running the python evaluator I get the following error:

Uncaught Error: spawn python3 ENOENT
(ENOENT is not found)

But I am able to run the same exact path with python....

python3 /Users/anon/Documents/AREPL/arepl-darwin-x64/arepl.app/Contents/Resources/app/src/python/pythonEvaluator.py

Not sure what's up with that.

Batch updates of stdout

It would be more efficient to update the html with prints in batches rather than doing it for every single call.

input gets interpreted as code if program is not running

print(input())

Type in 5 in the input box and press enter. You should see 5 appear back in output
Type in 5 again and you get an error in the console:

Uncaught Error: TypeError: 'int' object is not subscriptable
at PythonShell.parseError (C:\dev\arepl\node_modules\python-shell\index.js:183:17)
at terminateIfNeeded (C:\dev\arepl\node_modules\python-shell\index.js:98:28)
at ChildProcess. (C:\dev\arepl\node_modules\python-shell\index.js:88:9)
at emitTwo (events.js:106:13)
at ChildProcess.emit (events.js:194:7)
at Process.ChildProcess._handle.onexit (internal/child_process.js:215:12)
----- Python Traceback -----
File "C:\dev\arepl\src\python\pythonEvaluator.py", line 60, in
returnInfoJSON = exec_input(data['evalCode'])

If program is not running input should be ignored or (even better) the program should be restarted so the user can see the change in output with the new input

((k,v) for (k,v) in dictVar) causes error

does not work:

d = {'a':5}
x = ((k,v) for (k,v) in d)

does work:

d = {'a':5}
x = ((k,v) for (k,v) in d.items())
x = [(k,v) for k,v in d.items()]
x = {k:v for k,v in d.items()}
x = ((k) for k in d)

โš  There has been a error when trying to display your variables. Sorry :(

Traceback (most recent call last):
File "C:\Users\anon\Downloads\arepl-win32-x64\arepl-win32-x64\resources\app\src\python\pythonEvaluator.py", line 77, in exec_input
returnInfo['userVariables'] = jsonpickle.encode(userVariables, max_depth=100) # any depth above 245 resuls in error and anything above 100 takes too long to process
File "C:\Users\anon\Downloads\arepl-win32-x64\arepl-win32-x64\resources\app\src\python\jsonpickle_init_.py", line 135, in encode
numeric_keys=numeric_keys)
File "C:\Users\anon\Downloads\arepl-win32-x64\arepl-win32-x64\resources\app\src\python\jsonpickle\pickler.py", line 44, in encode
return backend.encode(context.flatten(value, reset=reset))
File "C:\Users\anon\Downloads\arepl-win32-x64\arepl-win32-x64\resources\app\src\python\jsonpickle\pickler.py", line 157, in flatten
return self._flatten(obj)
File "C:\Users\anon\Downloads\arepl-win32-x64\arepl-win32-x64\resources\app\src\python\jsonpickle\pickler.py", line 161, in _flatten
return self._pop(self._flatten_obj(obj))
File "C:\Users\anon\Downloads\arepl-win32-x64\arepl-win32-x64\resources\app\src\python\jsonpickle\pickler.py", line 177, in _flatten_obj
return flatten_func(obj)
File "C:\Users\anon\Downloads\arepl-win32-x64\arepl-win32-x64\resources\app\src\python\jsonpickle\pickler.py", line 429, in _flatten_dict_obj
flatten(k, v, data)
File "C:\Users\anon\Downloads\arepl-win32-x64\arepl-win32-x64\resources\app\src\python\jsonpickle\pickler.py", line 498, in _flatten_key_value_pair
data[k] = self._flatten(v)
File "C:\Users\anon\Downloads\arepl-win32-x64\arepl-win32-x64\resources\app\src\python\jsonpickle\pickler.py", line 161, in _flatten
return self._pop(self._flatten_obj(obj))
File "C:\Users\anon\Downloads\arepl-win32-x64\arepl-win32-x64\resources\app\src\python\jsonpickle\pickler.py", line 177, in _flatten_obj
return flatten_func(obj)
File "C:\Users\anon\Downloads\arepl-win32-x64\arepl-win32-x64\resources\app\src\python\jsonpickle\pickler.py", line 235, in _ref_obj_instance
return self._flatten_obj_instance(obj)
File "C:\Users\anon\Downloads\arepl-win32-x64\arepl-win32-x64\resources\app\src\python\jsonpickle\pickler.py", line 367, in _flatten_obj_instance
data[tags.ITERATOR] = list(map(self._flatten, islice(obj, self._max_iter)))
File "", line 2, in
ValueError: not enough values to unpack (expected 2, got 1)

Restart does not work

I made the mistake of assuming pyshell.end would terminate the process. What it actually does is just close the standard input stream. When I realized this I had to kill the child directly: ๐Ÿ”ช

pyshell.childProcess.kill();

But the kid still wouldn't die, so I gave the kid some time to run and sent SIGKILL over to finish the job:

pyshell.childProcess.kill();
setTimeout(()=>{
	dead = this.pyshell.childProcess.kill('SIGKILL');
}, 50);

But dead was false -> it was still alive! I went into the kill method and found this:

  if (this._handle) {
    var err = this._handle.kill(signal);
    if (err === 0) {
      /* Success. */
      this.killed = true;
      return true;
    }
    if (err === uv.UV_ESRCH) {
      /* Already dead. */
    } else if (err === uv.UV_EINVAL || err === uv.UV_ENOSYS) {
      /* The underlying platform doesn't support this signal. */
      throw errnoException(err, 'kill');
    } else {
      /* Other error, almost certainly EPERM. */
      this.emit('error', errnoException(err, 'kill'));
    }
  }

  /* Kill didn't succeed. */
  return false;

this._handle was null, so if(this._handle) returned false, and the kill failed. But why was the handle null? What even is a handle?

  this._handle = new Process();

So the handle is the process, but if the process was null... does that mean... the process was dead already?

๐Ÿค”

Looking back at my code, I realized that in most scenarios* the first kill would work, causing the second kill to fail because the process was already dead.

  • If the process is not busy executing the users python code, it quits at end of standard input or SIGTERM. Otherwise it could potentially go on forever without a SIGKILL.

To fix this I added a simple check:

dead = pyshell.childProcess.kill();
if (!dead) pyshell.childProcess.kill('SIGKILL');

okay, everything is good to go know, right?

...right?

Wrong. I had registered a function to restart the process upon close, but the pyshell close event was not always firing! Time for some more debugging:

    this.childProcess.on('exit', function (code) {
        self.exitCode = code;
        terminateIfNeeded();
    });

    function terminateIfNeeded() {
        if (!self.stderrHasEnded || !self.stdoutHasEnded || self.exitCode == null) {
            return;
        }
        // ... code continues
    }

Pyshell only fires the close event if exitCode is not null, but the child_process documentation says:

The 'exit' event is emitted after the child process ends. If the process exited, code is the final exit code of the process, otherwise null. If the process terminated due to receipt of a signal, signal is the string name of the signal, otherwise null. One of the two will always be non-null.

It's worded a bit wierdly, but what it's saying is that if the process is closed due to a signal the exit code will be null. So pyshell only emits close in the opposite situation - if the process exits voluntarily. Why that is I do not know - either the pyshell code or documentation needs to be updated.

Instead of using pyshell's close event I just used the child_process close event directly:

this.pyshell.childProcess.on('exit',()=>{
	this.startPython();
});

Done! ๐ŸŽ‰

AREPL uses python which causes error on mac (where python refers to python 2)

In mac python refers to python 2 by default.

see https://stackoverflow.com/questions/5846167/how-to-change-default-python-version
same issue with ubuntu: https://askubuntu.com/questions/320996/how-to-make-python-program-command-execute-python-3

Uncaught Error: KeyError: '__loader__'
at PythonShell.parseError (/Users/anon/Documents/AREPL/node_modules/python-shell/index.js:183:17)
at terminateIfNeeded (/Users/anon/Documents/AREPL/node_modules/python-shell/index.js:98:28)
at ChildProcess. (/Users/anon/Documents/AREPL/node_modules/python-shell/index.js:88:9)
at emitTwo (events.js:106:13)
at ChildProcess.emit (events.js:194:7)
at Process.ChildProcess._handle.onexit (internal/child_process.js:215:12)
----- Python Traceback -----
File "/Users/anon/Documents/AREPL/src/python/pythonEvaluator.py", line 14, in
startingLocals[var] = locals()[var]

Execution takes far more time than it should

x = [[i for i in range(10000000)]]

Timings in ms:

List Size Python Time Total Time (py & JS)
10^4 0 23
10^5 2.98 225
10^6 48.1 2363
10^7 489 24337

I'd be okay with a doubling or even tripling of the execution time but this is clearly rediculous. Only ~2% of the execution time is actually spent executing the user's code. God knows what the computer is doing the rest of the time. Sipping martinis on the beach? ๐Ÿ–๏ธ ๐Ÿธ

resizeable editor

Currently there is no way of changing the editor size short of modifying the source code directly. Even if there was a nice setting to change, it would still be nice to change the size of the editor with a simple drag. Users may want to adjust the size of the editor depending on their preferences and the size of the user variable display on the right.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.