kopia lustrzana https://github.com/micropython/micropython-lib
Porównaj commity
7 Commity
73af895f11
...
4e43bc0c78
Autor | SHA1 | Data |
---|---|---|
Jonah Bron | 4e43bc0c78 | |
Jonah Bron | 17b7e0c665 | |
Damien George | 45ead11f96 | |
iabdalkader | 661efa48f0 | |
iabdalkader | 8ee876dcd6 | |
Jim Mussared | 5c7e3fc0bc | |
Damien George | 23df50d0ea |
|
@ -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")
|
||||
|
|
|
@ -4,6 +4,17 @@ import hmac
|
|||
import json
|
||||
from time import time
|
||||
|
||||
# Optionally depend on https://github.com/dmazzella/ucryptography
|
||||
try:
|
||||
# Try importing from ucryptography port.
|
||||
import cryptography
|
||||
from cryptography import hashes, ec, serialization, utils
|
||||
|
||||
_ec_supported = True
|
||||
except ImportError:
|
||||
# No cryptography library available, no EC256 support.
|
||||
_ec_supported = False
|
||||
|
||||
|
||||
def _to_b64url(data):
|
||||
return (
|
||||
|
@ -19,6 +30,28 @@ def _from_b64url(data):
|
|||
return binascii.a2b_base64(data.replace(b"-", b"+").replace(b"_", b"/") + b"===")
|
||||
|
||||
|
||||
def _sig_der_to_jws(signed):
|
||||
"""Accept a DER signature and convert to JSON Web Signature bytes.
|
||||
|
||||
`cryptography` produces signatures encoded in DER ASN.1 binary format.
|
||||
JSON Web Algorithm instead encodes the signature as the point coordinates
|
||||
as bigendian byte strings concatenated.
|
||||
|
||||
See https://datatracker.ietf.org/doc/html/rfc7518#section-3.4
|
||||
"""
|
||||
r, s = utils.decode_dss_signature(signed)
|
||||
return r.to_bytes(32, "big") + s.to_bytes(32, "big")
|
||||
|
||||
|
||||
def _sig_jws_to_der(signed):
|
||||
"""Accept a JSON Web Signature and convert to a DER signature.
|
||||
|
||||
See `_sig_der_to_jws()`
|
||||
"""
|
||||
r, s = int.from_bytes(signed[0:32], "big"), int.from_bytes(signed[32:], "big")
|
||||
return utils.encode_dss_signature(r, s)
|
||||
|
||||
|
||||
class exceptions:
|
||||
class PyJWTError(Exception):
|
||||
pass
|
||||
|
@ -37,19 +70,32 @@ class exceptions:
|
|||
|
||||
|
||||
def encode(payload, key, algorithm="HS256"):
|
||||
if algorithm != "HS256":
|
||||
if algorithm != "HS256" and algorithm != "ES256":
|
||||
raise exceptions.InvalidAlgorithmError
|
||||
|
||||
if isinstance(key, str):
|
||||
key = key.encode()
|
||||
header = _to_b64url(json.dumps({"typ": "JWT", "alg": algorithm}).encode())
|
||||
payload = _to_b64url(json.dumps(payload).encode())
|
||||
signature = _to_b64url(hmac.new(key, header + b"." + payload, hashlib.sha256).digest())
|
||||
|
||||
if algorithm == "HS256":
|
||||
if isinstance(key, str):
|
||||
key = key.encode()
|
||||
signature = _to_b64url(hmac.new(key, header + b"." + payload, hashlib.sha256).digest())
|
||||
elif algorithm == "ES256":
|
||||
if not _ec_supported:
|
||||
raise exceptions.InvalidAlgorithmError(
|
||||
"Required dependencies for ES256 are not available"
|
||||
)
|
||||
if isinstance(key, int):
|
||||
key = ec.derive_private_key(key, ec.SECP256R1())
|
||||
signature = _to_b64url(
|
||||
_sig_der_to_jws(key.sign(header + b"." + payload, ec.ECDSA(hashes.SHA256())))
|
||||
)
|
||||
|
||||
return (header + b"." + payload + b"." + signature).decode()
|
||||
|
||||
|
||||
def decode(token, key, algorithms=["HS256"]):
|
||||
if "HS256" not in algorithms:
|
||||
def decode(token, key, algorithms=["HS256", "ES256"]):
|
||||
if "HS256" not in algorithms and "ES256" not in algorithms:
|
||||
raise exceptions.InvalidAlgorithmError
|
||||
|
||||
parts = token.encode().split(b".")
|
||||
|
@ -63,14 +109,31 @@ def decode(token, key, algorithms=["HS256"]):
|
|||
except Exception:
|
||||
raise exceptions.InvalidTokenError
|
||||
|
||||
if header["alg"] not in algorithms or header["alg"] != "HS256":
|
||||
if header["alg"] not in algorithms or (header["alg"] != "HS256" and header["alg"] != "ES256"):
|
||||
raise exceptions.InvalidAlgorithmError
|
||||
|
||||
if isinstance(key, str):
|
||||
key = key.encode()
|
||||
calculated_signature = hmac.new(key, parts[0] + b"." + parts[1], hashlib.sha256).digest()
|
||||
if signature != calculated_signature:
|
||||
raise exceptions.InvalidSignatureError
|
||||
if header["alg"] == "HS256":
|
||||
if isinstance(key, str):
|
||||
key = key.encode()
|
||||
calculated_signature = hmac.new(key, parts[0] + b"." + parts[1], hashlib.sha256).digest()
|
||||
if signature != calculated_signature:
|
||||
raise exceptions.InvalidSignatureError
|
||||
elif header["alg"] == "ES256":
|
||||
if not _ec_supported:
|
||||
raise exceptions.InvalidAlgorithmError(
|
||||
"Required dependencies for ES256 are not available"
|
||||
)
|
||||
|
||||
if isinstance(key, bytes):
|
||||
key = ec.EllipticCurvePublicKey.from_encoded_point(key, ec.SECP256R1())
|
||||
try:
|
||||
key.verify(
|
||||
_sig_jws_to_der(signature),
|
||||
parts[0] + b"." + parts[1],
|
||||
ec.ECDSA(hashes.SHA256()),
|
||||
)
|
||||
except cryptography.exceptions.InvalidSignature:
|
||||
raise exceptions.InvalidSignatureError
|
||||
|
||||
if "exp" in payload:
|
||||
if time() > payload["exp"]:
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
metadata(version="0.1.0", pypi="pyjwt")
|
||||
metadata(
|
||||
version="0.2.0",
|
||||
pypi="pyjwt",
|
||||
description="""
|
||||
JWT library for MicroPython. Supports HMAC (HS256) encoding essentially.
|
||||
Optionally supports ECDSA (ES256) asymmetric-key signing/verification when the
|
||||
[dmazella/ucryptography](https://github.com/dmazzella/ucryptography/) library
|
||||
is available in the MicroPython firmware.
|
||||
""",
|
||||
)
|
||||
|
||||
require("hmac")
|
||||
|
||||
|
|
|
@ -1,28 +1,71 @@
|
|||
import jwt
|
||||
from time import time
|
||||
|
||||
"""
|
||||
Run tests by executing:
|
||||
|
||||
```
|
||||
mpremote fs cp jwt.py :lib/jwt.py + run test_jwt.py
|
||||
```
|
||||
|
||||
Only the full test suite can be run if
|
||||
[ucryptography](https://github.com/dmazzella/ucryptography) is present in the
|
||||
firmware.
|
||||
"""
|
||||
|
||||
# Indentation
|
||||
I = " "
|
||||
|
||||
print("Testing HS256")
|
||||
secret_key = "top-secret!"
|
||||
|
||||
token = jwt.encode({"user": "joe"}, secret_key, algorithm="HS256")
|
||||
print(token)
|
||||
decoded = jwt.decode(token, secret_key, algorithms=["HS256"])
|
||||
if decoded != {"user": "joe"}:
|
||||
raise Exception("Invalid decoded JWT")
|
||||
else:
|
||||
print("Encode/decode test: OK")
|
||||
print(I, "Encode/decode test: OK")
|
||||
|
||||
try:
|
||||
decoded = jwt.decode(token, "wrong-secret", algorithms=["HS256"])
|
||||
except jwt.exceptions.InvalidSignatureError:
|
||||
print("Invalid signature test: OK")
|
||||
print(I, "Invalid signature test: OK")
|
||||
else:
|
||||
raise Exception("Invalid JWT should have failed decoding")
|
||||
|
||||
token = jwt.encode({"user": "joe", "exp": time() - 1}, secret_key)
|
||||
print(token)
|
||||
try:
|
||||
decoded = jwt.decode(token, secret_key, algorithms=["HS256"])
|
||||
except jwt.exceptions.ExpiredSignatureError:
|
||||
print("Expired token test: OK")
|
||||
print(I, "Expired token test: OK")
|
||||
else:
|
||||
raise Exception("Expired JWT should have failed decoding")
|
||||
|
||||
|
||||
print("Testing ES256")
|
||||
try:
|
||||
from cryptography import ec
|
||||
except ImportError:
|
||||
raise Exception("No cryptography lib present, can't test ES256")
|
||||
|
||||
private_key = ec.derive_private_key(
|
||||
0xEB6DFB26C7A3C23D33C60F7C7BA61B6893451F2643E0737B20759E457825EE75, ec.SECP256R1()
|
||||
)
|
||||
wrong_private_key = ec.derive_private_key(
|
||||
0x25D91A0DA38F69283A0CE32B87D82817CA4E134A1693BE6083C2292BF562A451, ec.SECP256R1()
|
||||
)
|
||||
|
||||
token = jwt.encode({"user": "joe"}, private_key, algorithm="ES256")
|
||||
decoded = jwt.decode(token, private_key.public_key(), algorithms=["ES256"])
|
||||
if decoded != {"user": "joe"}:
|
||||
raise Exception("Invalid decoded JWT")
|
||||
else:
|
||||
print(I, "Encode/decode test: OK")
|
||||
|
||||
token = jwt.encode({"user": "joe"}, private_key, algorithm="ES256")
|
||||
try:
|
||||
decoded = jwt.decode(token + "a", wrong_private_key.public_key(), algorithms=["ES256"])
|
||||
except jwt.exceptions.InvalidSignatureError:
|
||||
print(I, "Invalid signature test: OK")
|
||||
else:
|
||||
raise Exception("Invalid JWT should have fialed decoding")
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
metadata(version="0.1.0")
|
||||
|
||||
package("json")
|
|
@ -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:
|
||||
|
|
|
@ -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