Skip to content

Commit

Permalink
Add new test snippets (feat_stdlib_only) for micropython-stdlib-stub
Browse files Browse the repository at this point in the history
Signed-off-by: Jos Verlinde <jos_verlinde@hotmail.com>
  • Loading branch information
Josverl committed Dec 14, 2023
1 parent 3ca2826 commit 780aa74
Show file tree
Hide file tree
Showing 17 changed files with 267 additions and 14 deletions.
54 changes: 54 additions & 0 deletions publish/micropython-stdlib-stubs/creation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@



1. copy typeshed/stdlib (from pyright fallback)
2, rename the stubs that are used internally, but are not part of micropython
- [ ] codecs
- [ ] contextlib
- [ ] contextvars
- [ ] dataclasses
- [ ] decimal
- [ ] enum
- [ ] fractions
- [ ] functools
- [ ] numbers
- [ ] queue
- [ ] selectors
- [ ] sre_compile
- [ ] sre_constants
- [ ] sre_parse

3. remove all stubs and stub-only packages that are not in micropython
- database stubs
- email
- http
- .........

4. make some customisations ( is this still needed?)
- sys.pyi - Add to the end of the file:
``` python
# MicroPython specific functions
# Copyright (c) 2023 Jos Verlinde

from typing import Optional
from _typeshed import Incomplete
def atexit(func:Optional[Callable[[],Any]]) -> Optional[Callable[[],Any]]:
"""\
Register func to be called upon termination. func must be a callable that takes no arguments,
or None to disable the call. The atexit function will return the previous value set by this function,
which is initially None.
Ports: Unix, Windows
"""
...

def print_exception(exc, file=sys.stdout, /):
"""Print exception with a traceback to a file-like object file (or sys.stdout by default)."""
...
```






3 changes: 0 additions & 3 deletions tests/quality_tests/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
{
"python.analysis.diagnosticMode": "workspace",
"python.analysis.typeCheckingMode": "basic",
"python.testing.pytestArgs": [
"."
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
}
5 changes: 5 additions & 0 deletions tests/quality_tests/feat_stdlib_only/check_bytes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
PING_MSG = b"ping"
channel = 5

check = PING_MSG + b"x"
check = PING_MSG + bytes([channel]) # type: ignore #TODO Operator "+" not supported for types "Literal[b"ping"]" and "bytes"
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from collections import namedtuple

MyTuple = namedtuple("MyTuple", ("id", "name"))

t1 = MyTuple(1, "foo") # type: ignore # TODO: collections.namedtuple is not callable
t2 = MyTuple(2, "bar") # type: ignore
print(t1.name)
assert t2.name == t2[1]

print(type(MyTuple))
print(type(t1))
print(type(t2))
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from collections import OrderedDict

# To make benefit of ordered keys, OrderedDict should be initialized
# from sequence of (key, value) pairs.
d = OrderedDict([("z", 1), ("a", 2)])
# More items can be added as usual

#TODO add to ordered dict : https://github.com/Josverl/micropython-stubber/issues/333
d["w"] = 5 # type: ignore
d["b"] = 3 # type: ignore
for k, v in d.items():
print(k, v)
10 changes: 10 additions & 0 deletions tests/quality_tests/feat_stdlib_only/check_hasable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""Validate that a type is hashable.
ref: https://github.com/Josverl/micropython-stubs/issues/723
"""

i = 0
d = {i: "a"}

type_text = "int"
if type_text in {"int", "float", "str", "bool", "tuple", "list", "dict"}:
order = 1
16 changes: 16 additions & 0 deletions tests/quality_tests/feat_stdlib_only/check_io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import io
from typing import IO, Any, Optional

alloc_size = 512


buffer_1 = io.StringIO("hello world")
buffer_2 = io.BytesIO(b"some initial binary data: \x00\x01") # type: ignore # TODO

stream = open("file")

buffer_3 = io.BufferedWriter(stream, 8) # type: ignore # TODO stdlib.io "TextIOWrapper" is incompatible with "RawIOBase"
print(buffer_3.write(bytearray(16))) # type: ignore # TODO stdlib.io "bytearray" is incompatible with protocol "ReadableBuffer"


stream.close()
60 changes: 60 additions & 0 deletions tests/quality_tests/feat_stdlib_only/check_os/check_files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# runs on MicroPython (and Python)
# get file and folder information and return this as JSON
# params : folder , traverse subdirectory , output format, gethash
# intended to allow simple processing of files
# jos_verlinde@hotmail.com
import json
import logging
import os
from typing import Any, Dict, List, Optional, Tuple, Union

import ubinascii # type: ignore
import uhashlib # type: ignore

logging.basicConfig(level=logging.DEBUG)
log = logging.getLogger(__name__)


def listdir(path=".", sub=False, JSON=True, gethash=False):
# Lists the file information of a folder
li :List[dict]= [] # type: List[dict]
if path == ".": # Get current folder name
path = os.getcwd()
files = os.listdir(path)
for file in files:
# get size of each file
info = {"Path": path, "Name": file, "Size": 0}
if path[-1] == "/":
full = "%s%s" % (path, file)
else:
full = "%s/%s" % (path, file)
log.debug("os.stat({})".format(full))
subdir = []
try:
stat = os.stat(full) # type: ignore
if stat[0] & 0x4000: # stat.S_IFDIR
info["Type"] = "dir"
# recurse folder(s)
if sub == True:
log.debug("Folder :{}".format(full))
subdir = listdir(path=full, sub=True, JSON=False, gethash=gethash)
else:
info["Size"] = stat[6]
info["Type"] = "file"
if gethash:
with open(full, "rb") as f:
h = uhashlib.sha256(f.read())
info["Hash"] = ubinascii.hexlify(h.digest())
except OSError as e:
log.error("error:{} processing file:{}".format(e, full))
info["OSError"] = e.args[0]
info["Type"] = "OSError"
info["Fullname"] = full
li.append(info)
# recurse folder(s)
if sub == True:
li = li + subdir
if JSON == True:
return json.dumps(li)
else:
return li
9 changes: 9 additions & 0 deletions tests/quality_tests/feat_stdlib_only/check_re/check-Match.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from typing_extensions import assert_type

import re
Substring ='.*Python'
String1 = "MicroPython"
m =re.match(Substring, String1)

assert m is not None
assert_type(m, re.Match[str])
15 changes: 15 additions & 0 deletions tests/quality_tests/feat_stdlib_only/check_re/check_compile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import re
from typing import Any, List, Union

from typing_extensions import assert_type

# As re doesn't support escapes itself, use of r"" strings is not
# recommended.
regex = re.compile("[\r\n]")

result = regex.split("line1\rline2\nline3\r\n")

assert_type(result, List[Union[str, Any]])

# Result:
# ['line1', 'line2', 'line3', '', '']
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

# ref: https://github.com/Josverl/micropython-stubber/issues/336
from sys import print_exception
32 changes: 32 additions & 0 deletions tests/quality_tests/feat_stdlib_only/check_sys/check_sys.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import sys

bits = 0
v = sys.maxsize
while v:
bits += 1
v >>= 1
if bits > 32:
# 64-bit (or more) platform
...
else:
# 32-bit (or less) platform
# Note that on 32-bit platform, value of bits may be less than 32
# (e.g. 31) due to peculiarities described above, so use "> 16",
# "> 32", "> 64" style of comparisons.
...

print(sys.version_info[0], sys.version_info[1], sys.version_info[2])
print(sys.implementation)


# Micropython Extensions
exc = Exception
sys.print_exception(exc)

port = sys.platform
if port in ["unix", "windows"]:

def byebye():
print("so long")

previous = sys.atexit(byebye) # type: ignore
22 changes: 22 additions & 0 deletions tests/quality_tests/feat_stdlib_only/pyrightconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"include": [
"."
],
"typeshedPaths": [
"./typings"
],
"exclude": [
".*",
"__*",
"**/typings"
],
"ignore": [
"**/typings"
],
"pythonVersion": "3.8",
"pythonPlatform": "Linux",
"verboseOutput": false,
"typeCheckingMode": "basic",
"typeshedPath": "./typings",
"reportMissingModuleSource": "none"
}
10 changes: 10 additions & 0 deletions tests/quality_tests/feat_stdlib_only/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
This folder contains python code snippets that are used to test the quality of the type-stubs.


The checks are specifically for the micropython-stdlib-stub distribution
that is used as a dependency in most other micropython-*-stubs .

The checks are run against the micropython-stdlib-stub distribution itself,
and should contain no reference to any other micropython-*-stubs distribution.

Please avoid references to `umodules` or modules such as `micropython` and `machine` in the snippets here.
Empty file.
7 changes: 4 additions & 3 deletions tests/quality_tests/snippets.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
"name": "feat_micropython",
"path": "feat_micropython"
},
{
"name": "feat_stdlib_only",
"path": "feat_stdlib_only"
},
{
"name": "feat_stdlib",
"path": "feat_stdlib"
Expand All @@ -55,9 +59,6 @@
{
"name": "snippets",
"path": "."
},
{
"path": "../repos/micropython-stubs"
}
],
"settings": {
Expand Down
11 changes: 3 additions & 8 deletions tests/quality_tests/test_stdlib.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
import json
import logging
import platform
import re
import subprocess
from pathlib import Path
from typing import Dict, List

import fasteners
import pytest
from packaging.version import Version

from test_snippets import SOURCES, port_and_board, run_pyright
from test_snippets import SOURCES, run_pyright

# only snippets tests
pytestmark = pytest.mark.snippets

log = logging.getLogger()

HERE = Path(__file__).parent.absolute()

@pytest.mark.parametrize("portboard", ["stdlib"],scope="session")
@pytest.mark.parametrize("version", ["-"],scope="session")
@pytest.mark.parametrize("feature", ["stdlib"],scope="session")
@pytest.mark.parametrize("stub_source", SOURCES,scope="session")
@pytest.mark.parametrize("snip_path", [Path('c:/develop/MyPython/micropython-stubs/tests/quality_tests/feat_stdlib')],scope="session")
@pytest.mark.parametrize("snip_path", [HERE / "feat_stdlib_only"],scope="session")
def test_stdlib_pyright(
type_stub_cache_path: Path,
stub_source: str,
Expand Down

0 comments on commit 780aa74

Please sign in to comment.