kopia lustrzana https://github.com/micropython/micropython-lib
Porównaj commity
20 Commity
e4c9e2eb24
...
b458c6ce6b
Autor | SHA1 | Data |
---|---|---|
Andrew Leech | b458c6ce6b | |
Damien George | 45ead11f96 | |
iabdalkader | 661efa48f0 | |
iabdalkader | 8ee876dcd6 | |
Jim Mussared | 5c7e3fc0bc | |
Damien George | 23df50d0ea | |
Andrew Leech | f2c95fda80 | |
Andrew Leech | c3870d36fb | |
Andrew Leech | 109711d911 | |
Oliver Robson | 7444302ac6 | |
Oliver Robson | ae19d103b3 | |
Andrew Leech | eb30d317f3 | |
Oliver Robson | de6b87184b | |
Oliver Robson | 979819a82b | |
Andrew Leech | 448c38618f | |
Andrew Leech | 1fe75b8544 | |
Andrew Leech | 796a5b93f5 | |
Andrew Leech | 023c58bb59 | |
Andrew Leech | aac74a8b0a | |
Andrew Leech | 82501d721f |
|
@ -26,7 +26,7 @@ THE SOFTWARE.
|
|||
|
||||
from senml import *
|
||||
import time
|
||||
from cbor2 import decoder
|
||||
import cbor2
|
||||
|
||||
pack = SenmlPack("device_name")
|
||||
|
||||
|
@ -38,5 +38,5 @@ while True:
|
|||
cbor_val = pack.to_cbor()
|
||||
print(cbor_val)
|
||||
print(cbor_val.hex())
|
||||
print(decoder.loads(cbor_val)) # convert to string again so we can print it.
|
||||
print(cbor2.loads(cbor_val)) # convert to string again so we can print it.
|
||||
time.sleep(1)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
metadata(
|
||||
description="SenML serialisation for MicroPython.",
|
||||
version="0.1.0",
|
||||
version="0.1.1",
|
||||
pypi_publish="micropython-senml",
|
||||
)
|
||||
|
||||
|
|
|
@ -27,8 +27,7 @@ THE SOFTWARE.
|
|||
from senml.senml_record import SenmlRecord
|
||||
from senml.senml_base import SenmlBase
|
||||
import json
|
||||
from cbor2 import encoder
|
||||
from cbor2 import decoder
|
||||
import cbor2
|
||||
|
||||
|
||||
class SenmlPackIterator:
|
||||
|
@ -278,7 +277,7 @@ class SenmlPack(SenmlBase):
|
|||
:param data: a byte array.
|
||||
:return: None
|
||||
"""
|
||||
records = decoder.loads(data) # load the raw senml data
|
||||
records = cbor2.loads(data) # load the raw senml data
|
||||
naming_map = {
|
||||
"bn": -2,
|
||||
"bt": -3,
|
||||
|
@ -320,7 +319,7 @@ class SenmlPack(SenmlBase):
|
|||
}
|
||||
converted = []
|
||||
self._build_rec_dict(naming_map, converted)
|
||||
return encoder.dumps(converted)
|
||||
return cbor2.dumps(converted)
|
||||
|
||||
def add(self, item):
|
||||
"""
|
||||
|
|
|
@ -24,5 +24,10 @@ THE SOFTWARE.
|
|||
"""
|
||||
|
||||
|
||||
from . import decoder
|
||||
from . import encoder
|
||||
from ._decoder import CBORDecoder
|
||||
from ._decoder import load
|
||||
from ._decoder import loads
|
||||
|
||||
from ._encoder import CBOREncoder
|
||||
from ._encoder import dump
|
||||
from ._encoder import dumps
|
||||
|
|
|
@ -24,16 +24,15 @@ THE SOFTWARE.
|
|||
"""
|
||||
|
||||
|
||||
from cbor2 import encoder
|
||||
from cbor2 import decoder
|
||||
import cbor2
|
||||
|
||||
input = [
|
||||
{"bn": "urn:dev:ow:10e2073a01080063", "u": "Cel", "t": 1.276020076e09, "v": 23.5},
|
||||
{"u": "Cel", "t": 1.276020091e09, "v": 23.6},
|
||||
]
|
||||
|
||||
data = encoder.dumps(input)
|
||||
data = cbor2.dumps(input)
|
||||
print(data)
|
||||
print(data.hex())
|
||||
text = decoder.loads(data)
|
||||
text = cbor2.loads(data)
|
||||
print(text)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
metadata(version="0.1.0", pypi="cbor2")
|
||||
metadata(version="1.0.0", pypi="cbor2")
|
||||
|
||||
package("cbor2")
|
||||
|
|
|
@ -0,0 +1,900 @@
|
|||
"""Debugger basics"""
|
||||
|
||||
# This is originally from cpython 3.10: https://raw.githubusercontent.com/python/cpython/3.10/Lib/bdb.py
|
||||
# Patches for micropython have been commented as such.
|
||||
|
||||
import fnmatch
|
||||
import sys
|
||||
import os
|
||||
|
||||
## MPY: no inspect module avaialble
|
||||
# from inspect import CO_GENERATOR, CO_COROUTINE, CO_ASYNC_GENERATOR
|
||||
|
||||
__all__ = ["BdbQuit", "Bdb", "Breakpoint"]
|
||||
|
||||
## MPY: These flags currently don't exist
|
||||
# GENERATOR_AND_COROUTINE_FLAGS = CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR
|
||||
|
||||
|
||||
class BdbQuit(Exception):
|
||||
"""Exception to give up completely."""
|
||||
|
||||
|
||||
class Bdb:
|
||||
"""Generic Python debugger base class.
|
||||
|
||||
This class takes care of details of the trace facility;
|
||||
a derived class should implement user interaction.
|
||||
The standard debugger class (pdb.Pdb) is an example.
|
||||
|
||||
The optional skip argument must be an iterable of glob-style
|
||||
module name patterns. The debugger will not step into frames
|
||||
that originate in a module that matches one of these patterns.
|
||||
Whether a frame is considered to originate in a certain module
|
||||
is determined by the __name__ in the frame globals.
|
||||
"""
|
||||
|
||||
def __init__(self, skip=None):
|
||||
self.skip = set(skip) if skip else None
|
||||
self.breaks = {}
|
||||
self.fncache = {}
|
||||
self.frame_returning = None
|
||||
|
||||
self._load_breaks()
|
||||
|
||||
def canonic(self, filename):
|
||||
"""Return canonical form of filename.
|
||||
|
||||
For real filenames, the canonical form is a case-normalized (on
|
||||
case insensitive filesystems) absolute path. 'Filenames' with
|
||||
angle brackets, such as "<stdin>", generated in interactive
|
||||
mode, are returned unchanged.
|
||||
"""
|
||||
if filename == "<" + filename[1:-1] + ">":
|
||||
return filename
|
||||
canonic = self.fncache.get(filename)
|
||||
if not canonic:
|
||||
canonic = os.path.abspath(filename)
|
||||
canonic = os.path.normcase(canonic)
|
||||
self.fncache[filename] = canonic
|
||||
return canonic
|
||||
|
||||
def reset(self):
|
||||
"""Set values of attributes as ready to start debugging."""
|
||||
import linecache
|
||||
linecache.checkcache()
|
||||
self.botframe = None
|
||||
self._set_stopinfo(None, None)
|
||||
|
||||
def trace_dispatch(self, frame, event, arg):
|
||||
"""Dispatch a trace function for debugged frames based on the event.
|
||||
|
||||
This function is installed as the trace function for debugged
|
||||
frames. Its return value is the new trace function, which is
|
||||
usually itself. The default implementation decides how to
|
||||
dispatch a frame, depending on the type of event (passed in as a
|
||||
string) that is about to be executed.
|
||||
|
||||
The event can be one of the following:
|
||||
line: A new line of code is going to be executed.
|
||||
call: A function is about to be called or another code block
|
||||
is entered.
|
||||
return: A function or other code block is about to return.
|
||||
exception: An exception has occurred.
|
||||
c_call: A C function is about to be called.
|
||||
c_return: A C function has returned.
|
||||
c_exception: A C function has raised an exception.
|
||||
|
||||
For the Python events, specialized functions (see the dispatch_*()
|
||||
methods) are called. For the C events, no action is taken.
|
||||
|
||||
The arg parameter depends on the previous event.
|
||||
"""
|
||||
if self.quitting:
|
||||
return # None
|
||||
if event == 'line':
|
||||
return self.dispatch_line(frame)
|
||||
if event == 'call':
|
||||
return self.dispatch_call(frame, arg)
|
||||
if event == 'return':
|
||||
return self.dispatch_return(frame, arg)
|
||||
if event == 'exception':
|
||||
return self.dispatch_exception(frame, arg)
|
||||
if event == 'c_call':
|
||||
return self.trace_dispatch
|
||||
if event == 'c_exception':
|
||||
return self.trace_dispatch
|
||||
if event == 'c_return':
|
||||
return self.trace_dispatch
|
||||
print('bdb.Bdb.dispatch: unknown debugging event:', repr(event))
|
||||
return self.trace_dispatch
|
||||
|
||||
def dispatch_line(self, frame):
|
||||
"""Invoke user function and return trace function for line event.
|
||||
|
||||
If the debugger stops on the current line, invoke
|
||||
self.user_line(). Raise BdbQuit if self.quitting is set.
|
||||
Return self.trace_dispatch to continue tracing in this scope.
|
||||
"""
|
||||
if self.stop_here(frame) or self.break_here(frame):
|
||||
self.user_line(frame)
|
||||
if self.quitting: raise BdbQuit
|
||||
return self.trace_dispatch
|
||||
|
||||
def is_coroutine(self, frame):
|
||||
## MPY: co_flags attrib not available, compatible method of detecting coroutine TBD
|
||||
# return frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS
|
||||
return False
|
||||
|
||||
|
||||
def dispatch_call(self, frame, arg):
|
||||
"""Invoke user function and return trace function for call event.
|
||||
|
||||
If the debugger stops on this function call, invoke
|
||||
self.user_call(). Raise BdbQuit if self.quitting is set.
|
||||
Return self.trace_dispatch to continue tracing in this scope.
|
||||
"""
|
||||
# XXX 'arg' is no longer used
|
||||
if self.botframe is None:
|
||||
# First call of dispatch since reset()
|
||||
self.botframe = frame.f_back # (CT) Note that this may also be None!
|
||||
return self.trace_dispatch
|
||||
if not (self.stop_here(frame) or self.break_anywhere(frame)):
|
||||
# No need to trace this function
|
||||
return # None
|
||||
# Ignore call events in generator except when stepping.
|
||||
if self.stopframe and self.is_coroutine(frame):
|
||||
return self.trace_dispatch
|
||||
self.user_call(frame, arg)
|
||||
if self.quitting: raise BdbQuit
|
||||
return self.trace_dispatch
|
||||
|
||||
def dispatch_return(self, frame, arg):
|
||||
"""Invoke user function and return trace function for return event.
|
||||
|
||||
If the debugger stops on this function return, invoke
|
||||
self.user_return(). Raise BdbQuit if self.quitting is set.
|
||||
Return self.trace_dispatch to continue tracing in this scope.
|
||||
"""
|
||||
if self.stop_here(frame) or frame == self.returnframe:
|
||||
# Ignore return events in generator except when stepping.
|
||||
if self.stopframe and self.is_coroutine(frame):
|
||||
return self.trace_dispatch
|
||||
try:
|
||||
self.frame_returning = frame
|
||||
self.user_return(frame, arg)
|
||||
finally:
|
||||
self.frame_returning = None
|
||||
if self.quitting: raise BdbQuit
|
||||
# The user issued a 'next' or 'until' command.
|
||||
if self.stopframe is frame and self.stoplineno != -1:
|
||||
self._set_stopinfo(None, None)
|
||||
return self.trace_dispatch
|
||||
|
||||
def dispatch_exception(self, frame, arg):
|
||||
"""Invoke user function and return trace function for exception event.
|
||||
|
||||
If the debugger stops on this exception, invoke
|
||||
self.user_exception(). Raise BdbQuit if self.quitting is set.
|
||||
Return self.trace_dispatch to continue tracing in this scope.
|
||||
"""
|
||||
if self.stop_here(frame):
|
||||
# When stepping with next/until/return in a generator frame, skip
|
||||
# the internal StopIteration exception (with no traceback)
|
||||
# triggered by a subiterator run with the 'yield from' statement.
|
||||
if not (self.is_coroutine(frame)
|
||||
and arg[0] is StopIteration and arg[2] is None):
|
||||
self.user_exception(frame, arg)
|
||||
if self.quitting: raise BdbQuit
|
||||
# Stop at the StopIteration or GeneratorExit exception when the user
|
||||
# has set stopframe in a generator by issuing a return command, or a
|
||||
# next/until command at the last statement in the generator before the
|
||||
# exception.
|
||||
elif (self.stopframe and frame is not self.stopframe
|
||||
and self.is_coroutine(self.stopframe)
|
||||
and arg[0] in (StopIteration, GeneratorExit)):
|
||||
self.user_exception(frame, arg)
|
||||
if self.quitting: raise BdbQuit
|
||||
|
||||
return self.trace_dispatch
|
||||
|
||||
# Normally derived classes don't override the following
|
||||
# methods, but they may if they want to redefine the
|
||||
# definition of stopping and breakpoints.
|
||||
|
||||
def is_skipped_module(self, module_name):
|
||||
"Return True if module_name matches any skip pattern."
|
||||
if module_name is None: # some modules do not have names
|
||||
return False
|
||||
for pattern in self.skip:
|
||||
if fnmatch.fnmatch(module_name, pattern):
|
||||
return True
|
||||
return False
|
||||
|
||||
def stop_here(self, frame):
|
||||
"Return True if frame is below the starting frame in the stack."
|
||||
# (CT) stopframe may now also be None, see dispatch_call.
|
||||
# (CT) the former test for None is therefore removed from here.
|
||||
if self.skip and \
|
||||
self.is_skipped_module(frame.f_globals.get('__name__')):
|
||||
return False
|
||||
if frame is self.stopframe:
|
||||
if self.stoplineno == -1:
|
||||
return False
|
||||
return frame.f_lineno >= self.stoplineno
|
||||
if not self.stopframe:
|
||||
return True
|
||||
return False
|
||||
|
||||
def break_here(self, frame):
|
||||
"""Return True if there is an effective breakpoint for this line.
|
||||
|
||||
Check for line or function breakpoint and if in effect.
|
||||
Delete temporary breakpoints if effective() says to.
|
||||
"""
|
||||
filename = self.canonic(frame.f_code.co_filename)
|
||||
if filename not in self.breaks:
|
||||
return False
|
||||
lineno = frame.f_lineno
|
||||
if lineno not in self.breaks[filename]:
|
||||
# The line itself has no breakpoint, but maybe the line is the
|
||||
# first line of a function with breakpoint set by function name.
|
||||
lineno = frame.f_code.co_firstlineno
|
||||
if lineno not in self.breaks[filename]:
|
||||
return False
|
||||
|
||||
# flag says ok to delete temp. bp
|
||||
(bp, flag) = effective(filename, lineno, frame)
|
||||
if bp:
|
||||
self.currentbp = bp.number
|
||||
if (flag and bp.temporary):
|
||||
self.do_clear(str(bp.number))
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def do_clear(self, arg):
|
||||
"""Remove temporary breakpoint.
|
||||
|
||||
Must implement in derived classes or get NotImplementedError.
|
||||
"""
|
||||
raise NotImplementedError("subclass of bdb must implement do_clear()")
|
||||
|
||||
def break_anywhere(self, frame):
|
||||
"""Return True if there is any breakpoint for frame's filename.
|
||||
"""
|
||||
return self.canonic(frame.f_code.co_filename) in self.breaks
|
||||
|
||||
# Derived classes should override the user_* methods
|
||||
# to gain control.
|
||||
|
||||
def user_call(self, frame, argument_list):
|
||||
"""Called if we might stop in a function."""
|
||||
pass
|
||||
|
||||
def user_line(self, frame):
|
||||
"""Called when we stop or break at a line."""
|
||||
pass
|
||||
|
||||
def user_return(self, frame, return_value):
|
||||
"""Called when a return trap is set here."""
|
||||
pass
|
||||
|
||||
def user_exception(self, frame, exc_info):
|
||||
"""Called when we stop on an exception."""
|
||||
pass
|
||||
|
||||
def _set_stopinfo(self, stopframe, returnframe, stoplineno=0):
|
||||
"""Set the attributes for stopping.
|
||||
|
||||
If stoplineno is greater than or equal to 0, then stop at line
|
||||
greater than or equal to the stopline. If stoplineno is -1, then
|
||||
don't stop at all.
|
||||
"""
|
||||
self.stopframe = stopframe
|
||||
self.returnframe = returnframe
|
||||
self.quitting = False
|
||||
# stoplineno >= 0 means: stop at line >= the stoplineno
|
||||
# stoplineno -1 means: don't stop at all
|
||||
self.stoplineno = stoplineno
|
||||
|
||||
# Derived classes and clients can call the following methods
|
||||
# to affect the stepping state.
|
||||
|
||||
def set_until(self, frame, lineno=None):
|
||||
"""Stop when the line with the lineno greater than the current one is
|
||||
reached or when returning from current frame."""
|
||||
# the name "until" is borrowed from gdb
|
||||
if lineno is None:
|
||||
lineno = frame.f_lineno + 1
|
||||
self._set_stopinfo(frame, frame, lineno)
|
||||
|
||||
def set_step(self):
|
||||
"""Stop after one line of code."""
|
||||
# Issue #13183: pdb skips frames after hitting a breakpoint and running
|
||||
# step commands.
|
||||
# Restore the trace function in the caller (that may not have been set
|
||||
# for performance reasons) when returning from the current frame.
|
||||
if self.frame_returning:
|
||||
caller_frame = self.frame_returning.f_back
|
||||
if caller_frame and not caller_frame.f_trace:
|
||||
caller_frame.f_trace = self.trace_dispatch
|
||||
self._set_stopinfo(None, None)
|
||||
|
||||
def set_next(self, frame):
|
||||
"""Stop on the next line in or below the given frame."""
|
||||
self._set_stopinfo(frame, None)
|
||||
|
||||
def set_return(self, frame):
|
||||
"""Stop when returning from the given frame."""
|
||||
if self.is_coroutine(frame):
|
||||
self._set_stopinfo(frame, None, -1)
|
||||
else:
|
||||
self._set_stopinfo(frame.f_back, frame)
|
||||
|
||||
def set_trace(self, frame=None):
|
||||
"""Start debugging from frame.
|
||||
|
||||
If frame is not specified, debugging starts from caller's frame.
|
||||
"""
|
||||
if frame is None:
|
||||
frame = sys._getframe().f_back
|
||||
self.reset()
|
||||
while frame:
|
||||
frame.f_trace = self.trace_dispatch
|
||||
self.botframe = frame
|
||||
frame = frame.f_back
|
||||
self.set_step()
|
||||
sys.settrace(self.trace_dispatch)
|
||||
|
||||
def set_continue(self):
|
||||
"""Stop only at breakpoints or when finished.
|
||||
|
||||
If there are no breakpoints, set the system trace function to None.
|
||||
"""
|
||||
# Don't stop except at breakpoints or when finished
|
||||
self._set_stopinfo(self.botframe, None, -1)
|
||||
if not self.breaks:
|
||||
# no breakpoints; run without debugger overhead
|
||||
sys.settrace(None)
|
||||
frame = sys._getframe().f_back
|
||||
while frame and frame is not self.botframe:
|
||||
del frame.f_trace
|
||||
frame = frame.f_back
|
||||
|
||||
def set_quit(self):
|
||||
"""Set quitting attribute to True.
|
||||
|
||||
Raises BdbQuit exception in the next call to a dispatch_*() method.
|
||||
"""
|
||||
self.stopframe = self.botframe
|
||||
self.returnframe = None
|
||||
self.quitting = True
|
||||
sys.settrace(None)
|
||||
|
||||
# Derived classes and clients can call the following methods
|
||||
# to manipulate breakpoints. These methods return an
|
||||
# error message if something went wrong, None if all is well.
|
||||
# Set_break prints out the breakpoint line and file:lineno.
|
||||
# Call self.get_*break*() to see the breakpoints or better
|
||||
# for bp in Breakpoint.bpbynumber: if bp: bp.bpprint().
|
||||
|
||||
def _add_to_breaks(self, filename, lineno):
|
||||
"""Add breakpoint to breaks, if not already there."""
|
||||
bp_linenos = self.breaks.setdefault(filename, [])
|
||||
if lineno not in bp_linenos:
|
||||
bp_linenos.append(lineno)
|
||||
|
||||
def set_break(self, filename, lineno, temporary=False, cond=None,
|
||||
funcname=None):
|
||||
"""Set a new breakpoint for filename:lineno.
|
||||
|
||||
If lineno doesn't exist for the filename, return an error message.
|
||||
The filename should be in canonical form.
|
||||
"""
|
||||
filename = self.canonic(filename)
|
||||
import linecache # Import as late as possible
|
||||
line = linecache.getline(filename, lineno)
|
||||
if not line:
|
||||
return 'Line %s:%d does not exist' % (filename, lineno)
|
||||
self._add_to_breaks(filename, lineno)
|
||||
bp = Breakpoint(filename, lineno, temporary, cond, funcname)
|
||||
return None
|
||||
|
||||
def _load_breaks(self):
|
||||
"""Apply all breakpoints (set in other instances) to this one.
|
||||
|
||||
Populates this instance's breaks list from the Breakpoint class's
|
||||
list, which can have breakpoints set by another Bdb instance. This
|
||||
is necessary for interactive sessions to keep the breakpoints
|
||||
active across multiple calls to run().
|
||||
"""
|
||||
for (filename, lineno) in Breakpoint.bplist.keys():
|
||||
self._add_to_breaks(filename, lineno)
|
||||
|
||||
def _prune_breaks(self, filename, lineno):
|
||||
"""Prune breakpoints for filename:lineno.
|
||||
|
||||
A list of breakpoints is maintained in the Bdb instance and in
|
||||
the Breakpoint class. If a breakpoint in the Bdb instance no
|
||||
longer exists in the Breakpoint class, then it's removed from the
|
||||
Bdb instance.
|
||||
"""
|
||||
if (filename, lineno) not in Breakpoint.bplist:
|
||||
self.breaks[filename].remove(lineno)
|
||||
if not self.breaks[filename]:
|
||||
del self.breaks[filename]
|
||||
|
||||
def clear_break(self, filename, lineno):
|
||||
"""Delete breakpoints for filename:lineno.
|
||||
|
||||
If no breakpoints were set, return an error message.
|
||||
"""
|
||||
filename = self.canonic(filename)
|
||||
if filename not in self.breaks:
|
||||
return 'There are no breakpoints in %s' % filename
|
||||
if lineno not in self.breaks[filename]:
|
||||
return 'There is no breakpoint at %s:%d' % (filename, lineno)
|
||||
# If there's only one bp in the list for that file,line
|
||||
# pair, then remove the breaks entry
|
||||
for bp in Breakpoint.bplist[filename, lineno][:]:
|
||||
bp.deleteMe()
|
||||
self._prune_breaks(filename, lineno)
|
||||
return None
|
||||
|
||||
def clear_bpbynumber(self, arg):
|
||||
"""Delete a breakpoint by its index in Breakpoint.bpbynumber.
|
||||
|
||||
If arg is invalid, return an error message.
|
||||
"""
|
||||
try:
|
||||
bp = self.get_bpbynumber(arg)
|
||||
except ValueError as err:
|
||||
return str(err)
|
||||
bp.deleteMe()
|
||||
self._prune_breaks(bp.file, bp.line)
|
||||
return None
|
||||
|
||||
def clear_all_file_breaks(self, filename):
|
||||
"""Delete all breakpoints in filename.
|
||||
|
||||
If none were set, return an error message.
|
||||
"""
|
||||
filename = self.canonic(filename)
|
||||
if filename not in self.breaks:
|
||||
return 'There are no breakpoints in %s' % filename
|
||||
for line in self.breaks[filename]:
|
||||
blist = Breakpoint.bplist[filename, line]
|
||||
for bp in blist:
|
||||
bp.deleteMe()
|
||||
del self.breaks[filename]
|
||||
return None
|
||||
|
||||
def clear_all_breaks(self):
|
||||
"""Delete all existing breakpoints.
|
||||
|
||||
If none were set, return an error message.
|
||||
"""
|
||||
if not self.breaks:
|
||||
return 'There are no breakpoints'
|
||||
for bp in Breakpoint.bpbynumber:
|
||||
if bp:
|
||||
bp.deleteMe()
|
||||
self.breaks = {}
|
||||
return None
|
||||
|
||||
def get_bpbynumber(self, arg):
|
||||
"""Return a breakpoint by its index in Breakpoint.bybpnumber.
|
||||
|
||||
For invalid arg values or if the breakpoint doesn't exist,
|
||||
raise a ValueError.
|
||||
"""
|
||||
if not arg:
|
||||
raise ValueError('Breakpoint number expected')
|
||||
try:
|
||||
number = int(arg)
|
||||
except ValueError:
|
||||
raise ValueError('Non-numeric breakpoint number %s' % arg) from None
|
||||
try:
|
||||
bp = Breakpoint.bpbynumber[number]
|
||||
except IndexError:
|
||||
raise ValueError('Breakpoint number %d out of range' % number) from None
|
||||
if bp is None:
|
||||
raise ValueError('Breakpoint %d already deleted' % number)
|
||||
return bp
|
||||
|
||||
def get_break(self, filename, lineno):
|
||||
"""Return True if there is a breakpoint for filename:lineno."""
|
||||
filename = self.canonic(filename)
|
||||
return filename in self.breaks and \
|
||||
lineno in self.breaks[filename]
|
||||
|
||||
def get_breaks(self, filename, lineno):
|
||||
"""Return all breakpoints for filename:lineno.
|
||||
|
||||
If no breakpoints are set, return an empty list.
|
||||
"""
|
||||
filename = self.canonic(filename)
|
||||
return filename in self.breaks and \
|
||||
lineno in self.breaks[filename] and \
|
||||
Breakpoint.bplist[filename, lineno] or []
|
||||
|
||||
def get_file_breaks(self, filename):
|
||||
"""Return all lines with breakpoints for filename.
|
||||
|
||||
If no breakpoints are set, return an empty list.
|
||||
"""
|
||||
filename = self.canonic(filename)
|
||||
if filename in self.breaks:
|
||||
return self.breaks[filename]
|
||||
else:
|
||||
return []
|
||||
|
||||
def get_all_breaks(self):
|
||||
"""Return all breakpoints that are set."""
|
||||
return self.breaks
|
||||
|
||||
# Derived classes and clients can call the following method
|
||||
# to get a data structure representing a stack trace.
|
||||
|
||||
def get_stack(self, f, t):
|
||||
"""Return a list of (frame, lineno) in a stack trace and a size.
|
||||
|
||||
List starts with original calling frame, if there is one.
|
||||
Size may be number of frames above or below f.
|
||||
"""
|
||||
stack = []
|
||||
if t and t.tb_frame is f:
|
||||
t = t.tb_next
|
||||
while f is not None:
|
||||
stack.append((f, f.f_lineno))
|
||||
if f is self.botframe:
|
||||
break
|
||||
f = f.f_back
|
||||
stack.reverse()
|
||||
i = max(0, len(stack) - 1)
|
||||
while t is not None:
|
||||
stack.append((t.tb_frame, t.tb_lineno))
|
||||
t = t.tb_next
|
||||
if f is None:
|
||||
i = max(0, len(stack) - 1)
|
||||
return stack, i
|
||||
|
||||
def format_stack_entry(self, frame_lineno, lprefix=': '):
|
||||
"""Return a string with information about a stack entry.
|
||||
|
||||
The stack entry frame_lineno is a (frame, lineno) tuple. The
|
||||
return string contains the canonical filename, the function name
|
||||
or '<lambda>', the input arguments, the return value, and the
|
||||
line of code (if it exists).
|
||||
|
||||
"""
|
||||
## MPY: reprlib not yet available
|
||||
import linecache #, reprlib
|
||||
frame, lineno = frame_lineno
|
||||
filename = self.canonic(frame.f_code.co_filename)
|
||||
s = '%s(%r)' % (filename, lineno)
|
||||
if frame.f_code.co_name:
|
||||
s += frame.f_code.co_name
|
||||
else:
|
||||
s += "<lambda>"
|
||||
s += '()'
|
||||
if '__return__' in frame.f_locals:
|
||||
rv = frame.f_locals['__return__']
|
||||
s += '->'
|
||||
s += repr(rv)
|
||||
line = linecache.getline(filename, lineno, frame.f_globals)
|
||||
if line:
|
||||
s += lprefix + line.strip()
|
||||
return s
|
||||
|
||||
# The following methods can be called by clients to use
|
||||
# a debugger to debug a statement or an expression.
|
||||
# Both can be given as a string, or a code object.
|
||||
|
||||
def run(self, cmd, globals=None, locals=None):
|
||||
"""Debug a statement executed via the exec() function.
|
||||
|
||||
globals defaults to __main__.dict; locals defaults to globals.
|
||||
"""
|
||||
if globals is None:
|
||||
import __main__
|
||||
globals = __main__.__dict__
|
||||
if locals is None:
|
||||
locals = globals
|
||||
self.reset()
|
||||
if isinstance(cmd, str):
|
||||
cmd = compile(cmd, "<string>", "exec")
|
||||
sys.settrace(self.trace_dispatch)
|
||||
try:
|
||||
exec(cmd, globals, locals)
|
||||
except BdbQuit:
|
||||
pass
|
||||
finally:
|
||||
self.quitting = True
|
||||
sys.settrace(None)
|
||||
|
||||
def runeval(self, expr, globals=None, locals=None):
|
||||
"""Debug an expression executed via the eval() function.
|
||||
|
||||
globals defaults to __main__.dict; locals defaults to globals.
|
||||
"""
|
||||
if globals is None:
|
||||
import __main__
|
||||
globals = __main__.__dict__
|
||||
if locals is None:
|
||||
locals = globals
|
||||
self.reset()
|
||||
sys.settrace(self.trace_dispatch)
|
||||
try:
|
||||
return eval(expr, globals, locals)
|
||||
except BdbQuit:
|
||||
pass
|
||||
finally:
|
||||
self.quitting = True
|
||||
sys.settrace(None)
|
||||
|
||||
def runctx(self, cmd, globals, locals):
|
||||
"""For backwards-compatibility. Defers to run()."""
|
||||
# B/W compatibility
|
||||
self.run(cmd, globals, locals)
|
||||
|
||||
# This method is more useful to debug a single function call.
|
||||
|
||||
def runcall(self, func, *args, **kwds):
|
||||
"""Debug a single function call.
|
||||
|
||||
Return the result of the function call.
|
||||
"""
|
||||
self.reset()
|
||||
sys.settrace(self.trace_dispatch)
|
||||
res = None
|
||||
try:
|
||||
res = func(*args, **kwds)
|
||||
except BdbQuit:
|
||||
pass
|
||||
finally:
|
||||
self.quitting = True
|
||||
sys.settrace(None)
|
||||
return res
|
||||
|
||||
|
||||
def set_trace():
|
||||
"""Start debugging with a Bdb instance from the caller's frame."""
|
||||
Bdb().set_trace()
|
||||
|
||||
|
||||
class Breakpoint:
|
||||
"""Breakpoint class.
|
||||
|
||||
Implements temporary breakpoints, ignore counts, disabling and
|
||||
(re)-enabling, and conditionals.
|
||||
|
||||
Breakpoints are indexed by number through bpbynumber and by
|
||||
the (file, line) tuple using bplist. The former points to a
|
||||
single instance of class Breakpoint. The latter points to a
|
||||
list of such instances since there may be more than one
|
||||
breakpoint per line.
|
||||
|
||||
When creating a breakpoint, its associated filename should be
|
||||
in canonical form. If funcname is defined, a breakpoint hit will be
|
||||
counted when the first line of that function is executed. A
|
||||
conditional breakpoint always counts a hit.
|
||||
"""
|
||||
|
||||
# XXX Keeping state in the class is a mistake -- this means
|
||||
# you cannot have more than one active Bdb instance.
|
||||
|
||||
next = 1 # Next bp to be assigned
|
||||
bplist = {} # indexed by (file, lineno) tuple
|
||||
bpbynumber = [None] # Each entry is None or an instance of Bpt
|
||||
# index 0 is unused, except for marking an
|
||||
# effective break .... see effective()
|
||||
|
||||
def __init__(self, file, line, temporary=False, cond=None, funcname=None):
|
||||
self.funcname = funcname
|
||||
# Needed if funcname is not None.
|
||||
self.func_first_executable_line = None
|
||||
self.file = file # This better be in canonical form!
|
||||
self.line = line
|
||||
self.temporary = temporary
|
||||
self.cond = cond
|
||||
self.enabled = True
|
||||
self.ignore = 0
|
||||
self.hits = 0
|
||||
self.number = Breakpoint.next
|
||||
Breakpoint.next += 1
|
||||
# Build the two lists
|
||||
self.bpbynumber.append(self)
|
||||
if (file, line) in self.bplist:
|
||||
self.bplist[file, line].append(self)
|
||||
else:
|
||||
self.bplist[file, line] = [self]
|
||||
|
||||
@staticmethod
|
||||
def clearBreakpoints():
|
||||
Breakpoint.next = 1
|
||||
Breakpoint.bplist = {}
|
||||
Breakpoint.bpbynumber = [None]
|
||||
|
||||
def deleteMe(self):
|
||||
"""Delete the breakpoint from the list associated to a file:line.
|
||||
|
||||
If it is the last breakpoint in that position, it also deletes
|
||||
the entry for the file:line.
|
||||
"""
|
||||
|
||||
index = (self.file, self.line)
|
||||
self.bpbynumber[self.number] = None # No longer in list
|
||||
self.bplist[index].remove(self)
|
||||
if not self.bplist[index]:
|
||||
# No more bp for this f:l combo
|
||||
del self.bplist[index]
|
||||
|
||||
def enable(self):
|
||||
"""Mark the breakpoint as enabled."""
|
||||
self.enabled = True
|
||||
|
||||
def disable(self):
|
||||
"""Mark the breakpoint as disabled."""
|
||||
self.enabled = False
|
||||
|
||||
def bpprint(self, out=None):
|
||||
"""Print the output of bpformat().
|
||||
|
||||
The optional out argument directs where the output is sent
|
||||
and defaults to standard output.
|
||||
"""
|
||||
if out is None:
|
||||
out = sys.stdout
|
||||
print(self.bpformat(), file=out)
|
||||
|
||||
def bpformat(self):
|
||||
"""Return a string with information about the breakpoint.
|
||||
|
||||
The information includes the breakpoint number, temporary
|
||||
status, file:line position, break condition, number of times to
|
||||
ignore, and number of times hit.
|
||||
|
||||
"""
|
||||
if self.temporary:
|
||||
disp = 'del '
|
||||
else:
|
||||
disp = 'keep '
|
||||
if self.enabled:
|
||||
disp = disp + 'yes '
|
||||
else:
|
||||
disp = disp + 'no '
|
||||
ret = '%-4dbreakpoint %s at %s:%d' % (self.number, disp,
|
||||
self.file, self.line)
|
||||
if self.cond:
|
||||
ret += '\n\tstop only if %s' % (self.cond,)
|
||||
if self.ignore:
|
||||
ret += '\n\tignore next %d hits' % (self.ignore,)
|
||||
if self.hits:
|
||||
if self.hits > 1:
|
||||
ss = 's'
|
||||
else:
|
||||
ss = ''
|
||||
ret += '\n\tbreakpoint already hit %d time%s' % (self.hits, ss)
|
||||
return ret
|
||||
|
||||
def __str__(self):
|
||||
"Return a condensed description of the breakpoint."
|
||||
return 'breakpoint %s at %s:%s' % (self.number, self.file, self.line)
|
||||
|
||||
# -----------end of Breakpoint class----------
|
||||
|
||||
|
||||
def checkfuncname(b, frame):
|
||||
"""Return True if break should happen here.
|
||||
|
||||
Whether a break should happen depends on the way that b (the breakpoint)
|
||||
was set. If it was set via line number, check if b.line is the same as
|
||||
the one in the frame. If it was set via function name, check if this is
|
||||
the right function and if it is on the first executable line.
|
||||
"""
|
||||
if not b.funcname:
|
||||
# Breakpoint was set via line number.
|
||||
if b.line != frame.f_lineno:
|
||||
# Breakpoint was set at a line with a def statement and the function
|
||||
# defined is called: don't break.
|
||||
return False
|
||||
return True
|
||||
|
||||
# Breakpoint set via function name.
|
||||
if frame.f_code.co_name != b.funcname:
|
||||
# It's not a function call, but rather execution of def statement.
|
||||
return False
|
||||
|
||||
# We are in the right frame.
|
||||
if not b.func_first_executable_line:
|
||||
# The function is entered for the 1st time.
|
||||
b.func_first_executable_line = frame.f_lineno
|
||||
|
||||
if b.func_first_executable_line != frame.f_lineno:
|
||||
# But we are not at the first line number: don't break.
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
# Determines if there is an effective (active) breakpoint at this
|
||||
# line of code. Returns breakpoint number or 0 if none
|
||||
def effective(file, line, frame):
|
||||
"""Determine which breakpoint for this file:line is to be acted upon.
|
||||
|
||||
Called only if we know there is a breakpoint at this location. Return
|
||||
the breakpoint that was triggered and a boolean that indicates if it is
|
||||
ok to delete a temporary breakpoint. Return (None, None) if there is no
|
||||
matching breakpoint.
|
||||
"""
|
||||
possibles = Breakpoint.bplist[file, line]
|
||||
for b in possibles:
|
||||
if not b.enabled:
|
||||
continue
|
||||
if not checkfuncname(b, frame):
|
||||
continue
|
||||
# Count every hit when bp is enabled
|
||||
b.hits += 1
|
||||
if not b.cond:
|
||||
# If unconditional, and ignoring go on to next, else break
|
||||
if b.ignore > 0:
|
||||
b.ignore -= 1
|
||||
continue
|
||||
else:
|
||||
# breakpoint and marker that it's ok to delete if temporary
|
||||
return (b, True)
|
||||
else:
|
||||
# Conditional bp.
|
||||
# Ignore count applies only to those bpt hits where the
|
||||
# condition evaluates to true.
|
||||
try:
|
||||
val = eval(b.cond, frame.f_globals, frame.f_locals)
|
||||
if val:
|
||||
if b.ignore > 0:
|
||||
b.ignore -= 1
|
||||
# continue
|
||||
else:
|
||||
return (b, True)
|
||||
# else:
|
||||
# continue
|
||||
except:
|
||||
# if eval fails, most conservative thing is to stop on
|
||||
# breakpoint regardless of ignore count. Don't delete
|
||||
# temporary, as another hint to user.
|
||||
return (b, False)
|
||||
return (None, None)
|
||||
|
||||
|
||||
# -------------------- testing --------------------
|
||||
|
||||
class Tdb(Bdb):
|
||||
def user_call(self, frame, args):
|
||||
name = frame.f_code.co_name
|
||||
if not name: name = '???'
|
||||
print('+++ call', name, args)
|
||||
def user_line(self, frame):
|
||||
import linecache
|
||||
name = frame.f_code.co_name
|
||||
if not name: name = '???'
|
||||
fn = self.canonic(frame.f_code.co_filename)
|
||||
line = linecache.getline(fn, frame.f_lineno, frame.f_globals)
|
||||
print('+++', fn, frame.f_lineno, name, ':', line.strip())
|
||||
def user_return(self, frame, retval):
|
||||
print('+++ return', retval)
|
||||
def user_exception(self, frame, exc_stuff):
|
||||
print('+++ exception', exc_stuff)
|
||||
self.set_continue()
|
||||
|
||||
def foo(n):
|
||||
print('foo(', n, ')')
|
||||
x = bar(n*10)
|
||||
print('bar returned', x)
|
||||
|
||||
def bar(a):
|
||||
print('bar(', a, ')')
|
||||
return a/2
|
||||
|
||||
def test():
|
||||
t = Tdb()
|
||||
t.run('import bdb; bdb.foo(10)')
|
|
@ -0,0 +1,3 @@
|
|||
srctype = cpython
|
||||
type = module
|
||||
version = 0.0.1
|
|
@ -0,0 +1,24 @@
|
|||
import sys
|
||||
|
||||
# Remove current dir from sys.path, otherwise setuptools will peek up our
|
||||
# module instead of system's.
|
||||
sys.path.pop(0)
|
||||
from setuptools import setup
|
||||
|
||||
sys.path.append("..")
|
||||
import sdist_upip
|
||||
|
||||
setup(
|
||||
name="micropython-bdb",
|
||||
version="0.0.1",
|
||||
description="CPython bdb module ported to MicroPython",
|
||||
long_description="This is a module ported from CPython standard library to be compatible with\nMicroPython interpreter. Usually, this means applying small patches for\nfeatures not supported (yet, or at all) in MicroPython. Sometimes, heavier\nchanges are required. Note that CPython modules are written with availability\nof vast resources in mind, and may not work for MicroPython ports with\nlimited heap. If you are affected by such a case, please help reimplement\nthe module from scratch.",
|
||||
url="https://github.com/micropython/micropython-lib",
|
||||
author="CPython Developers",
|
||||
author_email="python-dev@python.org",
|
||||
maintainer="micropython-lib Developers",
|
||||
maintainer_email="micro-python@googlegroups.com",
|
||||
license="Python",
|
||||
cmdclass={"sdist": sdist_upip.sdist},
|
||||
py_modules=["bdb"],
|
||||
)
|
|
@ -85,13 +85,16 @@ class Cmd:
|
|||
nohelp = "*** No help on %s"
|
||||
use_rawinput = 1
|
||||
|
||||
def __init__(self, stdin=None, stdout=None):
|
||||
def __init__(self, completekey='tab', stdin=None, stdout=None):
|
||||
"""Instantiate a line-oriented interpreter framework.
|
||||
|
||||
The optional arguments stdin and stdout
|
||||
specify alternate input and output file objects; if not specified,
|
||||
sys.stdin and sys.stdout are used.
|
||||
|
||||
The optional argument completekey is not used, but provided for
|
||||
compatibility with calling libraries.
|
||||
|
||||
"""
|
||||
if stdin is not None:
|
||||
self.stdin = stdin
|
||||
|
|
|
@ -0,0 +1,315 @@
|
|||
"""Utilities needed to emulate Python's interactive interpreter.
|
||||
|
||||
"""
|
||||
|
||||
# Inspired by similar code by Jeff Epler and Fredrik Lundh.
|
||||
|
||||
|
||||
import sys
|
||||
import traceback
|
||||
from codeop import CommandCompiler, compile_command
|
||||
|
||||
__all__ = ["InteractiveInterpreter", "InteractiveConsole", "interact",
|
||||
"compile_command"]
|
||||
|
||||
class InteractiveInterpreter:
|
||||
"""Base class for InteractiveConsole.
|
||||
|
||||
This class deals with parsing and interpreter state (the user's
|
||||
namespace); it doesn't deal with input buffering or prompting or
|
||||
input file naming (the filename is always passed in explicitly).
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, locals=None):
|
||||
"""Constructor.
|
||||
|
||||
The optional 'locals' argument specifies the dictionary in
|
||||
which code will be executed; it defaults to a newly created
|
||||
dictionary with key "__name__" set to "__console__" and key
|
||||
"__doc__" set to None.
|
||||
|
||||
"""
|
||||
if locals is None:
|
||||
locals = {"__name__": "__console__", "__doc__": None}
|
||||
self.locals = locals
|
||||
self.compile = CommandCompiler()
|
||||
|
||||
def runsource(self, source, filename="<input>", symbol="single"):
|
||||
"""Compile and run some source in the interpreter.
|
||||
|
||||
Arguments are as for compile_command().
|
||||
|
||||
One of several things can happen:
|
||||
|
||||
1) The input is incorrect; compile_command() raised an
|
||||
exception (SyntaxError or OverflowError). A syntax traceback
|
||||
will be printed by calling the showsyntaxerror() method.
|
||||
|
||||
2) The input is incomplete, and more input is required;
|
||||
compile_command() returned None. Nothing happens.
|
||||
|
||||
3) The input is complete; compile_command() returned a code
|
||||
object. The code is executed by calling self.runcode() (which
|
||||
also handles run-time exceptions, except for SystemExit).
|
||||
|
||||
The return value is True in case 2, False in the other cases (unless
|
||||
an exception is raised). The return value can be used to
|
||||
decide whether to use sys.ps1 or sys.ps2 to prompt the next
|
||||
line.
|
||||
|
||||
"""
|
||||
try:
|
||||
code = self.compile(source, filename, symbol)
|
||||
except (OverflowError, SyntaxError, ValueError):
|
||||
# Case 1
|
||||
self.showsyntaxerror(filename)
|
||||
return False
|
||||
|
||||
if code is None:
|
||||
# Case 2
|
||||
return True
|
||||
|
||||
# Case 3
|
||||
self.runcode(code)
|
||||
return False
|
||||
|
||||
def runcode(self, code):
|
||||
"""Execute a code object.
|
||||
|
||||
When an exception occurs, self.showtraceback() is called to
|
||||
display a traceback. All exceptions are caught except
|
||||
SystemExit, which is reraised.
|
||||
|
||||
A note about KeyboardInterrupt: this exception may occur
|
||||
elsewhere in this code, and may not always be caught. The
|
||||
caller should be prepared to deal with it.
|
||||
|
||||
"""
|
||||
try:
|
||||
exec(code, self.locals)
|
||||
except SystemExit:
|
||||
raise
|
||||
except:
|
||||
self.showtraceback()
|
||||
|
||||
def showsyntaxerror(self, filename=None):
|
||||
"""Display the syntax error that just occurred.
|
||||
|
||||
This doesn't display a stack trace because there isn't one.
|
||||
|
||||
If a filename is given, it is stuffed in the exception instead
|
||||
of what was there before (because Python's parser always uses
|
||||
"<string>" when reading from a string).
|
||||
|
||||
The output is written by self.write(), below.
|
||||
|
||||
"""
|
||||
type, value, tb = sys.exc_info()
|
||||
sys.last_type = type
|
||||
sys.last_value = value
|
||||
sys.last_traceback = tb
|
||||
if filename and type is SyntaxError:
|
||||
# Work hard to stuff the correct filename in the exception
|
||||
try:
|
||||
msg, (dummy_filename, lineno, offset, line) = value.args
|
||||
except ValueError:
|
||||
# Not the format we expect; leave it alone
|
||||
pass
|
||||
else:
|
||||
# Stuff in the right filename
|
||||
value = SyntaxError(msg, (filename, lineno, offset, line))
|
||||
sys.last_value = value
|
||||
if sys.excepthook is sys.__excepthook__:
|
||||
lines = traceback.format_exception_only(type, value)
|
||||
self.write(''.join(lines))
|
||||
else:
|
||||
# If someone has set sys.excepthook, we let that take precedence
|
||||
# over self.write
|
||||
sys.excepthook(type, value, tb)
|
||||
|
||||
def showtraceback(self):
|
||||
"""Display the exception that just occurred.
|
||||
|
||||
We remove the first stack item because it is our own code.
|
||||
|
||||
The output is written by self.write(), below.
|
||||
|
||||
"""
|
||||
sys.last_type, sys.last_value, last_tb = ei = sys.exc_info()
|
||||
sys.last_traceback = last_tb
|
||||
try:
|
||||
lines = traceback.format_exception(ei[0], ei[1], last_tb.tb_next)
|
||||
if sys.excepthook is sys.__excepthook__:
|
||||
self.write(''.join(lines))
|
||||
else:
|
||||
# If someone has set sys.excepthook, we let that take precedence
|
||||
# over self.write
|
||||
sys.excepthook(ei[0], ei[1], last_tb)
|
||||
finally:
|
||||
last_tb = ei = None
|
||||
|
||||
def write(self, data):
|
||||
"""Write a string.
|
||||
|
||||
The base implementation writes to sys.stderr; a subclass may
|
||||
replace this with a different implementation.
|
||||
|
||||
"""
|
||||
sys.stderr.write(data)
|
||||
|
||||
|
||||
class InteractiveConsole(InteractiveInterpreter):
|
||||
"""Closely emulate the behavior of the interactive Python interpreter.
|
||||
|
||||
This class builds on InteractiveInterpreter and adds prompting
|
||||
using the familiar sys.ps1 and sys.ps2, and input buffering.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, locals=None, filename="<console>"):
|
||||
"""Constructor.
|
||||
|
||||
The optional locals argument will be passed to the
|
||||
InteractiveInterpreter base class.
|
||||
|
||||
The optional filename argument should specify the (file)name
|
||||
of the input stream; it will show up in tracebacks.
|
||||
|
||||
"""
|
||||
InteractiveInterpreter.__init__(self, locals)
|
||||
self.filename = filename
|
||||
self.resetbuffer()
|
||||
|
||||
def resetbuffer(self):
|
||||
"""Reset the input buffer."""
|
||||
self.buffer = []
|
||||
|
||||
def interact(self, banner=None, exitmsg=None):
|
||||
"""Closely emulate the interactive Python console.
|
||||
|
||||
The optional banner argument specifies the banner to print
|
||||
before the first interaction; by default it prints a banner
|
||||
similar to the one printed by the real Python interpreter,
|
||||
followed by the current class name in parentheses (so as not
|
||||
to confuse this with the real interpreter -- since it's so
|
||||
close!).
|
||||
|
||||
The optional exitmsg argument specifies the exit message
|
||||
printed when exiting. Pass the empty string to suppress
|
||||
printing an exit message. If exitmsg is not given or None,
|
||||
a default message is printed.
|
||||
|
||||
"""
|
||||
## MPY: Older versions of mpy don't support setting ps1 & ps2.
|
||||
ps1 = ">>> "
|
||||
ps2 = "... "
|
||||
try:
|
||||
ps1 = sys.ps1
|
||||
ps2 = sys.ps2
|
||||
except:
|
||||
pass
|
||||
cprt = 'Type "help", "copyright", "credits" or "license" for more information.'
|
||||
if banner is None:
|
||||
self.write("Python %s on %s\n%s\n(%s)\n" %
|
||||
(sys.version, sys.platform, cprt,
|
||||
self.__class__.__name__))
|
||||
elif banner:
|
||||
self.write("%s\n" % str(banner))
|
||||
more = 0
|
||||
while 1:
|
||||
try:
|
||||
if more:
|
||||
prompt = ps2
|
||||
else:
|
||||
prompt = ps1
|
||||
try:
|
||||
line = self.raw_input(prompt)
|
||||
except EOFError:
|
||||
self.write("\n")
|
||||
break
|
||||
else:
|
||||
more = self.push(line)
|
||||
except KeyboardInterrupt:
|
||||
self.write("\nKeyboardInterrupt\n")
|
||||
self.resetbuffer()
|
||||
more = 0
|
||||
if exitmsg is None:
|
||||
self.write('now exiting %s...\n' % self.__class__.__name__)
|
||||
elif exitmsg != '':
|
||||
self.write('%s\n' % exitmsg)
|
||||
|
||||
def push(self, line):
|
||||
"""Push a line to the interpreter.
|
||||
|
||||
The line should not have a trailing newline; it may have
|
||||
internal newlines. The line is appended to a buffer and the
|
||||
interpreter's runsource() method is called with the
|
||||
concatenated contents of the buffer as source. If this
|
||||
indicates that the command was executed or invalid, the buffer
|
||||
is reset; otherwise, the command is incomplete, and the buffer
|
||||
is left as it was after the line was appended. The return
|
||||
value is 1 if more input is required, 0 if the line was dealt
|
||||
with in some way (this is the same as runsource()).
|
||||
|
||||
"""
|
||||
self.buffer.append(line)
|
||||
source = "\n".join(self.buffer)
|
||||
more = self.runsource(source, self.filename)
|
||||
if not more:
|
||||
self.resetbuffer()
|
||||
return more
|
||||
|
||||
def raw_input(self, prompt=""):
|
||||
"""Write a prompt and read a line.
|
||||
|
||||
The returned line does not include the trailing newline.
|
||||
When the user enters the EOF key sequence, EOFError is raised.
|
||||
|
||||
The base implementation uses the built-in function
|
||||
input(); a subclass may replace this with a different
|
||||
implementation.
|
||||
|
||||
"""
|
||||
return input(prompt)
|
||||
|
||||
|
||||
|
||||
def interact(banner=None, readfunc=None, local=None, exitmsg=None):
|
||||
"""Closely emulate the interactive Python interpreter.
|
||||
|
||||
This is a backwards compatible interface to the InteractiveConsole
|
||||
class. When readfunc is not specified, it attempts to import the
|
||||
readline module to enable GNU readline if it is available.
|
||||
|
||||
Arguments (all optional, all default to None):
|
||||
|
||||
banner -- passed to InteractiveConsole.interact()
|
||||
readfunc -- if not None, replaces InteractiveConsole.raw_input()
|
||||
local -- passed to InteractiveInterpreter.__init__()
|
||||
exitmsg -- passed to InteractiveConsole.interact()
|
||||
|
||||
"""
|
||||
console = InteractiveConsole(local)
|
||||
if readfunc is not None:
|
||||
console.raw_input = readfunc
|
||||
else:
|
||||
try:
|
||||
import readline
|
||||
except ImportError:
|
||||
pass
|
||||
console.interact(banner, exitmsg)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-q', action='store_true',
|
||||
help="don't print version and copyright messages")
|
||||
args = parser.parse_args()
|
||||
if args.q or sys.flags.quiet:
|
||||
banner = ''
|
||||
else:
|
||||
banner = None
|
||||
interact(banner)
|
|
@ -0,0 +1,3 @@
|
|||
srctype = cpython
|
||||
type = module
|
||||
version = 0.0.1
|
|
@ -0,0 +1,24 @@
|
|||
import sys
|
||||
|
||||
# Remove current dir from sys.path, otherwise setuptools will peek up our
|
||||
# module instead of system's.
|
||||
sys.path.pop(0)
|
||||
from setuptools import setup
|
||||
|
||||
sys.path.append("..")
|
||||
import sdist_upip
|
||||
|
||||
setup(
|
||||
name="micropython-code",
|
||||
version="0.0.1",
|
||||
description="CPython code module ported to MicroPython",
|
||||
long_description="This is a module ported from CPython standard library to be compatible with\nMicroPython interpreter. Usually, this means applying small patches for\nfeatures not supported (yet, or at all) in MicroPython. Sometimes, heavier\nchanges are required. Note that CPython modules are written with availability\nof vast resources in mind, and may not work for MicroPython ports with\nlimited heap. If you are affected by such a case, please help reimplement\nthe module from scratch.",
|
||||
url="https://github.com/micropython/micropython-lib",
|
||||
author="CPython Developers",
|
||||
author_email="python-dev@python.org",
|
||||
maintainer="micropython-lib Developers",
|
||||
maintainer_email="micro-python@googlegroups.com",
|
||||
license="Python",
|
||||
cmdclass={"sdist": sdist_upip.sdist},
|
||||
py_modules=["code"],
|
||||
)
|
|
@ -0,0 +1,155 @@
|
|||
r"""Utilities to compile possibly incomplete Python source code.
|
||||
|
||||
This module provides two interfaces, broadly similar to the builtin
|
||||
function compile(), which take program text, a filename and a 'mode'
|
||||
and:
|
||||
|
||||
- Return code object if the command is complete and valid
|
||||
- Return None if the command is incomplete
|
||||
- Raise SyntaxError, ValueError or OverflowError if the command is a
|
||||
syntax error (OverflowError and ValueError can be produced by
|
||||
malformed literals).
|
||||
|
||||
The two interfaces are:
|
||||
|
||||
compile_command(source, filename, symbol):
|
||||
|
||||
Compiles a single command in the manner described above.
|
||||
|
||||
CommandCompiler():
|
||||
|
||||
Instances of this class have __call__ methods identical in
|
||||
signature to compile_command; the difference is that if the
|
||||
instance compiles program text containing a __future__ statement,
|
||||
the instance 'remembers' and compiles all subsequent program texts
|
||||
with the statement in force.
|
||||
|
||||
The module also provides another class:
|
||||
|
||||
Compile():
|
||||
|
||||
Instances of this class act like the built-in function compile,
|
||||
but with 'memory' in the sense described above.
|
||||
"""
|
||||
|
||||
# import __future__
|
||||
import warnings
|
||||
|
||||
## MPY: Future flags aren’t set on compiled code so just remove the checks
|
||||
# _features = [getattr(__future__, fname)
|
||||
# for fname in __future__.all_feature_names]
|
||||
|
||||
__all__ = ["compile_command", "Compile", "CommandCompiler"]
|
||||
|
||||
# The following flags match the values from Include/cpython/compile.h
|
||||
# Caveat emptor: These flags are undocumented on purpose and depending
|
||||
# on their effect outside the standard library is **unsupported**.
|
||||
PyCF_DONT_IMPLY_DEDENT = 0x200
|
||||
PyCF_ALLOW_INCOMPLETE_INPUT = 0x4000
|
||||
|
||||
def _maybe_compile(compiler, source, filename, symbol):
|
||||
# Check for source consisting of only blank lines and comments.
|
||||
for line in source.split("\n"):
|
||||
line = line.strip()
|
||||
if line and line[0] != '#':
|
||||
break # Leave it alone.
|
||||
else:
|
||||
if symbol != "eval":
|
||||
source = "pass" # Replace it with a 'pass' statement
|
||||
|
||||
try:
|
||||
return compiler(source, filename, symbol)
|
||||
except SyntaxError: # Let other compile() errors propagate.
|
||||
pass
|
||||
|
||||
# Catch syntax warnings after the first compile
|
||||
# to emit warnings (SyntaxWarning, DeprecationWarning) at most once.
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error")
|
||||
|
||||
try:
|
||||
compiler(source + "\n", filename, symbol)
|
||||
except SyntaxError as e:
|
||||
if "incomplete input" in str(e):
|
||||
return None
|
||||
raise
|
||||
|
||||
def _is_syntax_error(err1, err2):
|
||||
rep1 = repr(err1)
|
||||
rep2 = repr(err2)
|
||||
if "was never closed" in rep1 and "was never closed" in rep2:
|
||||
return False
|
||||
if rep1 == rep2:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _compile(source, filename, symbol):
|
||||
return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT)
|
||||
|
||||
def compile_command(source, filename="<input>", symbol="single"):
|
||||
r"""Compile a command and determine whether it is incomplete.
|
||||
|
||||
Arguments:
|
||||
|
||||
source -- the source string; may contain \n characters
|
||||
filename -- optional filename from which source was read; default
|
||||
"<input>"
|
||||
symbol -- optional grammar start symbol; "single" (default), "exec"
|
||||
or "eval"
|
||||
|
||||
Return value / exceptions raised:
|
||||
|
||||
- Return a code object if the command is complete and valid
|
||||
- Return None if the command is incomplete
|
||||
- Raise SyntaxError, ValueError or OverflowError if the command is a
|
||||
syntax error (OverflowError and ValueError can be produced by
|
||||
malformed literals).
|
||||
"""
|
||||
return _maybe_compile(_compile, source, filename, symbol)
|
||||
|
||||
class Compile:
|
||||
"""Instances of this class behave much like the built-in compile
|
||||
function, but if one is used to compile text containing a future
|
||||
statement, it "remembers" and compiles all subsequent program texts
|
||||
with the statement in force."""
|
||||
def __init__(self):
|
||||
self.flags = PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT
|
||||
|
||||
def __call__(self, source, filename, symbol):
|
||||
codeob = compile(source, filename, symbol, self.flags, True)
|
||||
## MPY: Future flags aren’t set on compiled code so just remove the checks
|
||||
# for feature in _features:
|
||||
# if codeob.co_flags & feature.compiler_flag:
|
||||
# self.flags |= feature.compiler_flag
|
||||
return codeob
|
||||
|
||||
class CommandCompiler:
|
||||
"""Instances of this class have __call__ methods identical in
|
||||
signature to compile_command; the difference is that if the
|
||||
instance compiles program text containing a __future__ statement,
|
||||
the instance 'remembers' and compiles all subsequent program texts
|
||||
with the statement in force."""
|
||||
|
||||
def __init__(self,):
|
||||
self.compiler = Compile()
|
||||
|
||||
def __call__(self, source, filename="<input>", symbol="single"):
|
||||
r"""Compile a command and determine whether it is incomplete.
|
||||
|
||||
Arguments:
|
||||
|
||||
source -- the source string; may contain \n characters
|
||||
filename -- optional filename from which source was read;
|
||||
default "<input>"
|
||||
symbol -- optional grammar start symbol; "single" (default) or
|
||||
"eval"
|
||||
|
||||
Return value / exceptions raised:
|
||||
|
||||
- Return a code object if the command is complete and valid
|
||||
- Return None if the command is incomplete
|
||||
- Raise SyntaxError, ValueError or OverflowError if the command is a
|
||||
syntax error (OverflowError and ValueError can be produced by
|
||||
malformed literals).
|
||||
"""
|
||||
return _maybe_compile(self.compiler, source, filename, symbol)
|
|
@ -0,0 +1,3 @@
|
|||
srctype = cpython
|
||||
type = module
|
||||
version = 0.0.1
|
|
@ -0,0 +1,24 @@
|
|||
import sys
|
||||
|
||||
# Remove current dir from sys.path, otherwise setuptools will peek up our
|
||||
# module instead of system's.
|
||||
sys.path.pop(0)
|
||||
from setuptools import setup
|
||||
|
||||
sys.path.append("..")
|
||||
import sdist_upip
|
||||
|
||||
setup(
|
||||
name="micropython-codeop",
|
||||
version="0.0.1",
|
||||
description="CPython codeop module ported to MicroPython",
|
||||
long_description="This is a module ported from CPython standard library to be compatible with\nMicroPython interpreter. Usually, this means applying small patches for\nfeatures not supported (yet, or at all) in MicroPython. Sometimes, heavier\nchanges are required. Note that CPython modules are written with availability\nof vast resources in mind, and may not work for MicroPython ports with\nlimited heap. If you are affected by such a case, please help reimplement\nthe module from scratch.",
|
||||
url="https://github.com/micropython/micropython-lib",
|
||||
author="CPython Developers",
|
||||
author_email="python-dev@python.org",
|
||||
maintainer="micropython-lib Developers",
|
||||
maintainer_email="micro-python@googlegroups.com",
|
||||
license="Python",
|
||||
cmdclass={"sdist": sdist_upip.sdist},
|
||||
py_modules=["codeop"],
|
||||
)
|
|
@ -1,3 +0,0 @@
|
|||
metadata(version="0.1.0")
|
||||
|
||||
package("json")
|
|
@ -0,0 +1,182 @@
|
|||
"""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", "lazycache"]
|
||||
|
||||
|
||||
# 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."""
|
||||
cache.clear()
|
||||
|
||||
|
||||
def getline(filename, lineno, module_globals=None):
|
||||
"""Get a line for a Python source file from the cache.
|
||||
Update the cache if it doesn't contain an entry for this file already."""
|
||||
|
||||
lines = getlines(filename, module_globals)
|
||||
if 1 <= lineno <= len(lines):
|
||||
return lines[lineno - 1]
|
||||
return ''
|
||||
|
||||
|
||||
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())
|
||||
elif 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:
|
||||
cache.pop(filename, None)
|
||||
continue
|
||||
if size != stat.st_size or mtime != stat.st_mtime:
|
||||
cache.pop(filename, None)
|
||||
|
||||
|
||||
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:
|
||||
cache.pop(filename, None)
|
||||
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 cacheable
|
||||
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 '__name__' in module_globals:
|
||||
name = module_globals['__name__']
|
||||
if (loader := module_globals.get('__loader__')) is None:
|
||||
if spec := module_globals.get('__spec__'):
|
||||
try:
|
||||
loader = spec.loader
|
||||
except AttributeError:
|
||||
pass
|
||||
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
|
|
@ -0,0 +1,3 @@
|
|||
srctype = cpython
|
||||
type = module
|
||||
version = 0.0.1
|
|
@ -0,0 +1,24 @@
|
|||
import sys
|
||||
|
||||
# Remove current dir from sys.path, otherwise setuptools will peek up our
|
||||
# module instead of system's.
|
||||
sys.path.pop(0)
|
||||
from setuptools import setup
|
||||
|
||||
sys.path.append("..")
|
||||
import sdist_upip
|
||||
|
||||
setup(
|
||||
name="micropython-linecache",
|
||||
version="0.0.1",
|
||||
description="CPython linecache module ported to MicroPython",
|
||||
long_description="This is a module ported from CPython standard library to be compatible with\nMicroPython interpreter. Usually, this means applying small patches for\nfeatures not supported (yet, or at all) in MicroPython. Sometimes, heavier\nchanges are required. Note that CPython modules are written with availability\nof vast resources in mind, and may not work for MicroPython ports with\nlimited heap. If you are affected by such a case, please help reimplement\nthe module from scratch.",
|
||||
url="https://github.com/micropython/micropython-lib",
|
||||
author="CPython Developers",
|
||||
author_email="python-dev@python.org",
|
||||
maintainer="micropython-lib Developers",
|
||||
maintainer_email="micro-python@googlegroups.com",
|
||||
license="Python",
|
||||
cmdclass={"sdist": sdist_upip.sdist},
|
||||
py_modules=["linecache"],
|
||||
)
|
|
@ -12,6 +12,10 @@ def normpath(s):
|
|||
return s
|
||||
|
||||
|
||||
def realpath(s):
|
||||
return s
|
||||
|
||||
|
||||
def abspath(s):
|
||||
if s[0] != "/":
|
||||
return os.getcwd() + "/" + s
|
||||
|
|
|
@ -1,8 +1,40 @@
|
|||
# Replace built-in os module.
|
||||
from uos import *
|
||||
# Include built-in os module.
|
||||
import sys
|
||||
|
||||
__path = sys.path
|
||||
try:
|
||||
sys.path.clear()
|
||||
from os import *
|
||||
finally:
|
||||
sys.path.extend(__path)
|
||||
|
||||
# Provide optional dependencies (which may be installed separately).
|
||||
try:
|
||||
from . import path
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
# https://docs.python.org/3/library/os.html#os.stat_result
|
||||
stat_result = namedtuple(
|
||||
"stat_result",
|
||||
(
|
||||
"st_mode",
|
||||
"st_ino",
|
||||
"st_dev",
|
||||
"st_nlink",
|
||||
"st_uid",
|
||||
"st_gid",
|
||||
"st_size",
|
||||
"st_atime",
|
||||
"st_mtime",
|
||||
"st_ctime",
|
||||
),
|
||||
)
|
||||
|
||||
__os_stat = stat
|
||||
|
||||
|
||||
def stat(path):
|
||||
return stat_result(*__os_stat(path))
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
srctype = cpython
|
||||
type = module
|
||||
version = 0.0.1
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,24 @@
|
|||
import sys
|
||||
|
||||
# Remove current dir from sys.path, otherwise setuptools will peek up our
|
||||
# module instead of system's.
|
||||
sys.path.pop(0)
|
||||
from setuptools import setup
|
||||
|
||||
sys.path.append("..")
|
||||
import sdist_upip
|
||||
|
||||
setup(
|
||||
name="micropython-pdb",
|
||||
version="0.0.1",
|
||||
description="CPython pdb module ported to MicroPython",
|
||||
long_description="This is a module ported from CPython standard library to be compatible with\nMicroPython interpreter. Usually, this means applying small patches for\nfeatures not supported (yet, or at all) in MicroPython. Sometimes, heavier\nchanges are required. Note that CPython modules are written with availability\nof vast resources in mind, and may not work for MicroPython ports with\nlimited heap. If you are affected by such a case, please help reimplement\nthe module from scratch.",
|
||||
url="https://github.com/micropython/micropython-lib",
|
||||
author="CPython Developers",
|
||||
author_email="python-dev@python.org",
|
||||
maintainer="micropython-lib Developers",
|
||||
maintainer_email="micro-python@googlegroups.com",
|
||||
license="Python",
|
||||
cmdclass={"sdist": sdist_upip.sdist},
|
||||
py_modules=["pdb"],
|
||||
)
|
|
@ -1,3 +1,3 @@
|
|||
metadata(version="0.2.0")
|
||||
metadata(version="0.2.1")
|
||||
|
||||
module("ssl.py", opt=3)
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
import tls
|
||||
from tls import (
|
||||
CERT_NONE,
|
||||
CERT_OPTIONAL,
|
||||
CERT_REQUIRED,
|
||||
MBEDTLS_VERSION,
|
||||
PROTOCOL_TLS_CLIENT,
|
||||
PROTOCOL_TLS_SERVER,
|
||||
)
|
||||
from tls import *
|
||||
|
||||
|
||||
class SSLContext:
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
srctype = micropython-lib
|
||||
type = module
|
||||
version = 1.0
|
||||
author = Andrew Leech
|
||||
long_desc = Minimal tokenize stub supporting open() in utf8 encoding.
|
|
@ -0,0 +1,8 @@
|
|||
from builtins import open as _builtin_open
|
||||
|
||||
|
||||
def open(filename):
|
||||
"""Open a file in read only text mode using utf8.
|
||||
"""
|
||||
return _builtin_open(filename, "r", encoding="utf8")
|
||||
|
|
@ -19,9 +19,13 @@ replacement for CPython.
|
|||
|
||||
### Usage
|
||||
|
||||
To use a unix-specific library, pass `unix_ffi=True` to `require()` in your
|
||||
manifest file.
|
||||
To use a unix-specific library, a manifest file must add the `unix-ffi`
|
||||
library to the library search path using `add_library()`:
|
||||
|
||||
```py
|
||||
require("os", unix_ffi=True) # Use the unix-ffi version instead of python-stdlib.
|
||||
add_library("unix-ffi", "$(MPY_LIB_DIR)/unix-ffi", prepend=True)
|
||||
```
|
||||
|
||||
Prepending the `unix-ffi` library to the path will make it so that the
|
||||
`unix-ffi` version of a package will be preferred if that package appears in
|
||||
both `unix-ffi` and another library (eg `python-stdlib`).
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
metadata(version="3.3.4")
|
||||
|
||||
require("re", unix_ffi=True)
|
||||
require("re")
|
||||
|
||||
module("_markupbase.py")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
metadata(version="0.5.1")
|
||||
|
||||
require("functools")
|
||||
require("email.encoders", unix_ffi=True)
|
||||
require("email.errors", unix_ffi=True)
|
||||
require("email.encoders")
|
||||
require("email.errors")
|
||||
|
||||
package("email")
|
||||
|
|
|
@ -3,7 +3,7 @@ metadata(version="0.5.1")
|
|||
require("base64")
|
||||
require("binascii")
|
||||
require("quopri")
|
||||
require("re", unix_ffi=True)
|
||||
require("re")
|
||||
require("string")
|
||||
|
||||
package("email")
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
metadata(version="0.5.1")
|
||||
|
||||
require("re", unix_ffi=True)
|
||||
require("email.errors", unix_ffi=True)
|
||||
require("email.message", unix_ffi=True)
|
||||
require("email.internal", unix_ffi=True)
|
||||
require("re")
|
||||
require("email.errors")
|
||||
require("email.message")
|
||||
require("email.internal")
|
||||
|
||||
package("email")
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
metadata(version="0.5.2")
|
||||
|
||||
require("re", unix_ffi=True)
|
||||
require("re")
|
||||
require("binascii")
|
||||
require("email.encoders", unix_ffi=True)
|
||||
require("email.errors", unix_ffi=True)
|
||||
require("email.charset", unix_ffi=True)
|
||||
require("email.encoders")
|
||||
require("email.errors")
|
||||
require("email.charset")
|
||||
|
||||
package("email")
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
metadata(version="0.5.1")
|
||||
|
||||
require("re", unix_ffi=True)
|
||||
require("re")
|
||||
require("base64")
|
||||
require("binascii")
|
||||
require("functools")
|
||||
require("string")
|
||||
# require("calendar") TODO
|
||||
require("abc")
|
||||
require("email.errors", unix_ffi=True)
|
||||
require("email.header", unix_ffi=True)
|
||||
require("email.charset", unix_ffi=True)
|
||||
require("email.utils", unix_ffi=True)
|
||||
require("email.errors")
|
||||
require("email.header")
|
||||
require("email.charset")
|
||||
require("email.utils")
|
||||
|
||||
package("email")
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
metadata(version="0.5.3")
|
||||
|
||||
require("re", unix_ffi=True)
|
||||
require("re")
|
||||
require("uu")
|
||||
require("base64")
|
||||
require("binascii")
|
||||
require("email.utils", unix_ffi=True)
|
||||
require("email.errors", unix_ffi=True)
|
||||
require("email.charset", unix_ffi=True)
|
||||
require("email.utils")
|
||||
require("email.errors")
|
||||
require("email.charset")
|
||||
|
||||
package("email")
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
metadata(version="0.5.1")
|
||||
|
||||
require("warnings")
|
||||
require("email.feedparser", unix_ffi=True)
|
||||
require("email.message", unix_ffi=True)
|
||||
require("email.internal", unix_ffi=True)
|
||||
require("email.feedparser")
|
||||
require("email.message")
|
||||
require("email.internal")
|
||||
|
||||
package("email")
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
metadata(version="3.3.4")
|
||||
|
||||
require("os", unix_ffi=True)
|
||||
require("re", unix_ffi=True)
|
||||
require("os")
|
||||
require("re")
|
||||
require("base64")
|
||||
require("random")
|
||||
require("datetime")
|
||||
require("urllib.parse", unix_ffi=True)
|
||||
require("urllib.parse")
|
||||
require("warnings")
|
||||
require("quopri")
|
||||
require("email.charset", unix_ffi=True)
|
||||
require("email.charset")
|
||||
|
||||
package("email")
|
||||
|
|
|
@ -2,6 +2,6 @@ metadata(version="0.0.4")
|
|||
|
||||
# Originally written by Paul Sokolovsky.
|
||||
|
||||
require("ffilib", unix_ffi=True)
|
||||
require("ffilib")
|
||||
|
||||
module("fcntl.py")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
metadata(version="3.3.4")
|
||||
|
||||
require("os", unix_ffi=True)
|
||||
require("os")
|
||||
|
||||
module("getopt.py")
|
||||
|
|
|
@ -2,6 +2,6 @@ metadata(version="0.1.0")
|
|||
|
||||
# Originally written by Riccardo Magliocchetti.
|
||||
|
||||
require("ffilib", unix_ffi=True)
|
||||
require("ffilib")
|
||||
|
||||
module("gettext.py")
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
metadata(version="0.5.2")
|
||||
|
||||
require("os", unix_ffi=True)
|
||||
require("os")
|
||||
require("os-path")
|
||||
require("re", unix_ffi=True)
|
||||
require("re")
|
||||
require("fnmatch")
|
||||
|
||||
module("glob.py")
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
metadata(version="3.3.4")
|
||||
|
||||
require("_markupbase", unix_ffi=True)
|
||||
require("_markupbase")
|
||||
require("warnings")
|
||||
require("html.entities", unix_ffi=True)
|
||||
require("re", unix_ffi=True)
|
||||
require("html.entities")
|
||||
require("re")
|
||||
|
||||
package("html")
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
metadata(version="0.5.1")
|
||||
|
||||
require("email.parser", unix_ffi=True)
|
||||
require("email.message", unix_ffi=True)
|
||||
require("socket", unix_ffi=True)
|
||||
require("email.parser")
|
||||
require("email.message")
|
||||
require("socket")
|
||||
require("collections")
|
||||
require("urllib.parse", unix_ffi=True)
|
||||
require("urllib.parse")
|
||||
require("warnings")
|
||||
|
||||
package("http")
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
metadata(version="0.2.0")
|
||||
|
||||
require("re")
|
||||
package("json")
|
|
@ -2,8 +2,8 @@ metadata(version="0.2.1")
|
|||
|
||||
# Originally written by Paul Sokolovsky.
|
||||
|
||||
require("ffilib", unix_ffi=True)
|
||||
require("os", unix_ffi=True)
|
||||
require("signal", unix_ffi=True)
|
||||
require("ffilib")
|
||||
require("os")
|
||||
require("signal")
|
||||
|
||||
package("machine")
|
||||
|
|
|
@ -2,8 +2,8 @@ metadata(version="0.1.2")
|
|||
|
||||
# Originally written by Paul Sokolovsky.
|
||||
|
||||
require("os", unix_ffi=True)
|
||||
require("select", unix_ffi=True)
|
||||
require("os")
|
||||
require("select")
|
||||
require("pickle")
|
||||
|
||||
module("multiprocessing.py")
|
||||
|
|
|
@ -2,7 +2,7 @@ metadata(version="0.6.0")
|
|||
|
||||
# Originally written by Paul Sokolovsky.
|
||||
|
||||
require("ffilib", unix_ffi=True)
|
||||
require("ffilib")
|
||||
require("errno")
|
||||
require("stat")
|
||||
|
||||
|
|
|
@ -2,6 +2,6 @@ metadata(version="0.1.0")
|
|||
|
||||
# Originally written by Riccardo Magliocchetti.
|
||||
|
||||
require("ffilib", unix_ffi=True)
|
||||
require("ffilib")
|
||||
|
||||
module("pwd.py")
|
||||
|
|
|
@ -2,6 +2,6 @@ metadata(version="0.2.5")
|
|||
|
||||
# Originally written by Paul Sokolovsky.
|
||||
|
||||
require("ffilib", unix_ffi=True)
|
||||
require("ffilib")
|
||||
|
||||
module("re.py")
|
||||
|
|
|
@ -2,7 +2,7 @@ metadata(version="0.3.0")
|
|||
|
||||
# Originally written by Paul Sokolovsky.
|
||||
|
||||
require("os", unix_ffi=True)
|
||||
require("ffilib", unix_ffi=True)
|
||||
require("os")
|
||||
require("ffilib")
|
||||
|
||||
module("select.py")
|
||||
|
|
|
@ -2,6 +2,6 @@ metadata(version="0.3.2")
|
|||
|
||||
# Originally written by Paul Sokolovsky.
|
||||
|
||||
require("ffilib", unix_ffi=True)
|
||||
require("ffilib")
|
||||
|
||||
module("signal.py")
|
||||
|
|
|
@ -2,6 +2,6 @@ metadata(version="0.2.4")
|
|||
|
||||
# Originally written by Paul Sokolovsky.
|
||||
|
||||
require("ffilib", unix_ffi=True)
|
||||
require("ffilib")
|
||||
|
||||
module("sqlite3.py")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
metadata(version="0.5.0")
|
||||
|
||||
require("ffilib", unix_ffi=True)
|
||||
require("ffilib")
|
||||
|
||||
module("time.py")
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
metadata(version="3.3.4")
|
||||
|
||||
require("getopt", unix_ffi=True)
|
||||
require("getopt")
|
||||
require("itertools")
|
||||
# require("linecache") TODO
|
||||
require("time", unix_ffi=True)
|
||||
require("time")
|
||||
require("traceback")
|
||||
|
||||
module("timeit.py")
|
||||
|
|
|
@ -2,8 +2,8 @@ metadata(version="0.1.2")
|
|||
|
||||
# Originally written by Paul Sokolovsky.
|
||||
|
||||
require("os", unix_ffi=True)
|
||||
require("tty", unix_ffi=True)
|
||||
require("select", unix_ffi=True)
|
||||
require("os")
|
||||
require("tty")
|
||||
require("select")
|
||||
|
||||
package("ucurses")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
metadata(version="0.5.2")
|
||||
|
||||
require("re", unix_ffi=True)
|
||||
require("re")
|
||||
require("collections")
|
||||
require("collections-defaultdict")
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue