From 19b23a15efa41c937ff549bcf5fe29d499968a3c Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Sun, 3 Nov 2024 23:12:12 +0100 Subject: [PATCH 01/17] Implement StringRef.__repr__() Signed-off-by: Manuel Saelices --- stdlib/src/utils/stringref.mojo | 26 ++++++++++++++++++++------ stdlib/test/utils/test_stringref.mojo | 6 ++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/stdlib/src/utils/stringref.mojo b/stdlib/src/utils/stringref.mojo index 89c0bb2711..0df7d32f89 100644 --- a/stdlib/src/utils/stringref.mojo +++ b/stdlib/src/utils/stringref.mojo @@ -41,17 +41,18 @@ fn _align_down(value: Int, alignment: Int) -> Int: @value @register_passable("trivial") struct StringRef( - Sized, - IntableRaising, + AsBytes, + Boolable, CollectionElement, CollectionElementNew, + Comparable, + Hashable, + IntableRaising, + Representable, + Sized, Stringable, Writable, - Hashable, _HashableWithHasher, - Boolable, - Comparable, - AsBytes, ): """ Represent a constant reference to a string, i.e. a sequence of characters @@ -398,6 +399,19 @@ struct StringRef( """ return String.write(self) + @no_inline + fn __repr__(self) -> String: + """Convert the string reference to a string. + + Returns: + The String representation of the StringRef. + """ + var output = String() + output.write("StringRef('") + self.write_to(output) + output.write("')") + return output + @no_inline fn write_to[W: Writer](self, inout writer: W): """ diff --git a/stdlib/test/utils/test_stringref.mojo b/stdlib/test/utils/test_stringref.mojo index 33c18c533f..c2fc074648 100644 --- a/stdlib/test/utils/test_stringref.mojo +++ b/stdlib/test/utils/test_stringref.mojo @@ -169,6 +169,11 @@ fn test_stringref_split() raises: assert_equal(res4[1], "o") +def test_str_and_ref(): + assert_equal(str(StringRef("abc")), String("abc")) + assert_equal(repr(StringRef("abc")), String("StringRef('abc')")) + + def main(): test_strref_from_start() test_stringref_split() @@ -177,3 +182,4 @@ def main(): test_indexing() test_find() test_endswith() + test_str_and_ref() From 950d36adbe5823c5611038669e14c2a9dd00f594 Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Sun, 3 Nov 2024 23:24:20 +0100 Subject: [PATCH 02/17] [stdlib] Faster path.stat() implementation using Writer Signed-off-by: Manuel Saelices --- stdlib/src/os/fstat.mojo | 51 +++++++++++++++++---------- stdlib/test/pathlib/test_pathlib.mojo | 31 ++++++++++++++++ 2 files changed, 64 insertions(+), 18 deletions(-) diff --git a/stdlib/src/os/fstat.mojo b/stdlib/src/os/fstat.mojo index f3d367944e..cf5fa31181 100644 --- a/stdlib/src/os/fstat.mojo +++ b/stdlib/src/os/fstat.mojo @@ -46,7 +46,7 @@ fn _constrain_unix(): @value -struct stat_result(Stringable): +struct stat_result(Stringable, Writable): """Object whose fields correspond to the members of the stat structure.""" var st_mode: Int @@ -150,6 +150,35 @@ struct stat_result(Stringable): self.st_rdev = st_rdev self.st_flags = st_flags + @no_inline + fn write_to[W: Writer](self, inout writer: W): + """ + Formats this path to the provided Writer. + + Parameters: + W: A type conforming to the Writable trait. + + Args: + writer: The object to write to. + """ + writer.write("os.stat_result(") + writer.write("st_mode=", self.st_mode) + writer.write(", st_ino=", self.st_ino) + writer.write(", st_dev=", self.st_dev) + writer.write(", st_nlink=", self.st_nlink) + writer.write(", st_uid=", self.st_uid) + writer.write(", st_gid=", self.st_gid) + writer.write(", st_size=", self.st_size) + writer.write(", st_atime=", str(self.st_atimespec)) + writer.write(", st_mtime=", str(self.st_mtimespec)) + writer.write(", st_ctime=", str(self.st_ctimespec)) + writer.write(", st_birthtime=", str(self.st_birthtimespec)) + writer.write(", st_blocks=", self.st_blocks) + writer.write(", st_blksize=", self.st_blksize) + writer.write(", st_rdev=", self.st_rdev) + writer.write(", st_flags=", self.st_flags) + writer.write(")") + @no_inline fn __str__(self) -> String: """Constructs a string representation of stat_result. @@ -157,23 +186,9 @@ struct stat_result(Stringable): Returns: A string representation of stat_result. """ - var res = String("os.stat_result(") - res += "st_mode=" + str(self.st_mode) - res += ", st_ino=" + str(self.st_ino) - res += ", st_dev=" + str(self.st_dev) - res += ", st_nlink=" + str(self.st_nlink) - res += ", st_uid=" + str(self.st_uid) - res += ", st_gid=" + str(self.st_gid) - res += ", st_size=" + str(self.st_size) - res += ", st_atime=" + str(self.st_atimespec) - res += ", st_mtime=" + str(self.st_mtimespec) - res += ", st_ctime=" + str(self.st_ctimespec) - res += ", st_birthtime=" + str(self.st_birthtimespec) - res += ", st_blocks=" + str(self.st_blocks) - res += ", st_blksize=" + str(self.st_blksize) - res += ", st_rdev=" + str(self.st_rdev) - res += ", st_flags=" + str(self.st_flags) - return res + ")" + var output = String() + self.write_to(output) + return output fn __repr__(self) -> String: """Constructs a representation of stat_result. diff --git a/stdlib/test/pathlib/test_pathlib.mojo b/stdlib/test/pathlib/test_pathlib.mojo index 249d5b2133..4ab12d3242 100644 --- a/stdlib/test/pathlib/test_pathlib.mojo +++ b/stdlib/test/pathlib/test_pathlib.mojo @@ -148,6 +148,36 @@ def test_home(): set_home(original_home) +def test_stat(): + var path = Path(__source_location().file_name) + var stat = path.stat() + assert_true(stat.st_mode > 0) + assert_true(stat.st_size > 0) + assert_equal( + str(stat), + "os.stat_result(st_mode={}, st_ino={}, st_dev={}, st_nlink={}," + " st_uid={}, st_gid={}, st_size={}, st_atime={}, st_mtime={}," + " st_ctime={}, st_birthtime={}, st_blocks={}, st_blksize={}," + " st_rdev={}, st_flags={})".format( + stat.st_mode, + stat.st_ino, + stat.st_dev, + stat.st_nlink, + stat.st_uid, + stat.st_gid, + stat.st_size, + str(stat.st_atimespec), + str(stat.st_mtimespec), + str(stat.st_ctimespec), + str(stat.st_birthtimespec), + stat.st_blocks, + stat.st_blksize, + stat.st_rdev, + stat.st_flags, + ), + ) + + def main(): test_cwd() test_path() @@ -159,3 +189,4 @@ def main(): test_read_write() test_expand_user() test_home() + test_stat() From c6c9277115753214943c5abcd73a792257032cfa Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Mon, 4 Nov 2024 00:25:17 +0100 Subject: [PATCH 03/17] Optimize String.__repr__() by using Writer Signed-off-by: Manuel Saelices --- stdlib/src/collections/string.mojo | 88 ++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 28 deletions(-) diff --git a/stdlib/src/collections/string.mojo b/stdlib/src/collections/string.mojo index 3f9e28aa47..5190c65842 100644 --- a/stdlib/src/collections/string.mojo +++ b/stdlib/src/collections/string.mojo @@ -686,6 +686,63 @@ fn isprintable(c: UInt8) -> Bool: return ord_space <= int(c) <= ord_tilde +# ===----------------------------------------------------------------------=== # +# String Representation +# ===----------------------------------------------------------------------=== # + + +struct StringRepr(Writable): + """Represents a string representation of an String.""" + + var _value: StringSlice[ImmutableAnyOrigin] + """The string representation of the String.""" + + fn __init__(inout self, value: String): + """Constructs a string representation of the string. + + Args: + value: The string to represent. + """ + self._value = StringSlice[ImmutableAnyOrigin]( + unsafe_from_utf8_ptr=value.unsafe_ptr(), + len=len(value), + ) + + fn write_to[W: Writer](self, inout writer: W): + """Writes the string representation to the provided writer. + + Parameters: + W: The type of the writer. + + Args: + writer: The writer to write the string representation to. + """ + var quote = "'" + if len(self._value) > 0 and self._value[0] == "'": + quote = '"' + writer.write(quote) + for s in self._value: + if s == "\\": + writer.write(r"\\") + elif s == "\t": + writer.write(r"\t") + elif s == "\n": + writer.write(r"\n") + elif s == "\r": + writer.write(r"\r") + else: + var codepoint = ord(s) + if isprintable(codepoint): + writer.write(s) + elif codepoint < 0x10: + writer.write(hex(codepoint, prefix=r"\x0")) + elif codepoint < 0x20 or codepoint == 0x7F: + writer.write(hex(codepoint, prefix=r"\x")) + else: # multi-byte character + writer.write(s) + writer.write(quote) + + # ===----------------------------------------------------------------------=== # # String # ===----------------------------------------------------------------------=== # @@ -1320,34 +1377,9 @@ struct String( Returns: A new representation of the string. """ - var result = String() - var use_dquote = False - for s in self: - use_dquote = use_dquote or (s == "'") - - if s == "\\": - result += r"\\" - elif s == "\t": - result += r"\t" - elif s == "\n": - result += r"\n" - elif s == "\r": - result += r"\r" - else: - var codepoint = ord(s) - if isprintable(codepoint): - result += s - elif codepoint < 0x10: - result += hex(codepoint, prefix=r"\x0") - elif codepoint < 0x20 or codepoint == 0x7F: - result += hex(codepoint, prefix=r"\x") - else: # multi-byte character - result += s - - if use_dquote: - return '"' + result + '"' - else: - return "'" + result + "'" + var output = String() + StringRepr(self).write_to(output) + return output fn __fspath__(self) -> String: """Return the file system path representation (just the string itself). From f1472b9754b17251c1fc4e91b9dad41ab4fcb9e5 Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Mon, 4 Nov 2024 00:51:18 +0100 Subject: [PATCH 04/17] [stdlib] Use StringRepr for StringRef.__repr__() This improves the representation to be like String.__repr__() Signed-off-by: Manuel Saelices --- stdlib/src/utils/stringref.mojo | 11 +++++++---- stdlib/test/utils/test_stringref.mojo | 18 ++++++++++++++++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/stdlib/src/utils/stringref.mojo b/stdlib/src/utils/stringref.mojo index 0df7d32f89..bea49b1a41 100644 --- a/stdlib/src/utils/stringref.mojo +++ b/stdlib/src/utils/stringref.mojo @@ -15,7 +15,7 @@ from bit import count_trailing_zeros from builtin.dtype import _uint_type_of_width -from collections.string import _atol, _isspace +from collections.string import _atol, _isspace, StringRepr from hashlib._hasher import _HashableWithHasher, _Hasher from memory import UnsafePointer, memcmp, pack_bits from memory.memory import _memcmp_impl_unconstrained @@ -407,9 +407,12 @@ struct StringRef( The String representation of the StringRef. """ var output = String() - output.write("StringRef('") - self.write_to(output) - output.write("')") + var to_str = str(self) + + output.write("StringRef(") + StringRepr(to_str).write_to(output) + output.write(")") + _ = to_str return output @no_inline diff --git a/stdlib/test/utils/test_stringref.mojo b/stdlib/test/utils/test_stringref.mojo index c2fc074648..0dc7686197 100644 --- a/stdlib/test/utils/test_stringref.mojo +++ b/stdlib/test/utils/test_stringref.mojo @@ -170,8 +170,22 @@ fn test_stringref_split() raises: def test_str_and_ref(): - assert_equal(str(StringRef("abc")), String("abc")) - assert_equal(repr(StringRef("abc")), String("StringRef('abc')")) + assert_equal(StringRef("abc").__str__(), "abc") + assert_equal(StringRef("abc").__repr__(), "StringRef('abc')") + assert_equal(StringRef("\0").__repr__(), r"StringRef('\x00')") + assert_equal(StringRef("\x09").__repr__(), r"StringRef('\t')") + assert_equal(StringRef("\n").__repr__(), r"StringRef('\n')") + assert_equal(StringRef("\x0d").__repr__(), r"StringRef('\r')") + assert_equal(StringRef("'").__repr__(), 'StringRef("\'")') + + # Multi-byte characters.__repr__() + assert_equal( + StringRef("Örnsköldsvik").__repr__(), "StringRef('Örnsköldsvik')" + ) # 2-byte + assert_equal(StringRef("你好!").__repr__(), "StringRef('你好!')") # 3-byte + assert_equal( + StringRef("hello 🔥!").__repr__(), "StringRef('hello 🔥!')" + ) # 4-byte def main(): From 3fbb842cd898d7c3882aec944b3442c4f2c7acf4 Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Mon, 4 Nov 2024 00:54:23 +0100 Subject: [PATCH 05/17] Add changelog entry Signed-off-by: Manuel Saelices --- docs/changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index ebd5e3e49b..8ef0029a77 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -16,6 +16,9 @@ what we publish. ### ⭐️ New +- `StringRef` is now representable so `repr(StringRef("hello"))` will return + `StringRef('hello')`. + - Mojo can now interpret simple LLVM intrinsics in parameter expressions, enabling things like `count_leading_zeros` to work at compile time: [Issue #933](https://github.com/modularml/mojo/issues/933). From 3c2129f2bbcd21b5eccce8ec71fe38df94c8c39a Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Thu, 7 Nov 2024 22:38:15 +0100 Subject: [PATCH 06/17] [stdlib] Faster UInt.__repr__() Signed-off-by: Manuel Saelices --- stdlib/src/builtin/uint.mojo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/src/builtin/uint.mojo b/stdlib/src/builtin/uint.mojo index 9c744052df..37d408aaad 100644 --- a/stdlib/src/builtin/uint.mojo +++ b/stdlib/src/builtin/uint.mojo @@ -149,7 +149,7 @@ struct UInt(IntLike, _HashableWithHasher): Returns: The string representation of this UInt. """ - return "UInt(" + str(self) + ")" + return String.write("UInt(", str(self), ")") fn __hash__(self) -> UInt: """Hash the UInt using builtin hash. From 91f0b80c8fe7f9320829045446c58fe2b316a1d8 Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Thu, 7 Nov 2024 22:39:55 +0100 Subject: [PATCH 07/17] [stdlib] Faster Error.__repr__() Signed-off-by: Manuel Saelices --- stdlib/src/builtin/error.mojo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/src/builtin/error.mojo b/stdlib/src/builtin/error.mojo index a974d6a8c2..ea7c6a8076 100644 --- a/stdlib/src/builtin/error.mojo +++ b/stdlib/src/builtin/error.mojo @@ -180,7 +180,7 @@ struct Error( Returns: A printable representation of the error message. """ - return "Error(" + repr(self._message()) + ")" + return String.write("Error(", repr(self._message()), ")") # ===-------------------------------------------------------------------===# # Methods From db15abe85420637c093d7e5cd0a55d91148ad1bb Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Thu, 7 Nov 2024 22:43:52 +0100 Subject: [PATCH 08/17] [stdlib] Faster DType.__repr__() Signed-off-by: Manuel Saelices --- stdlib/src/builtin/dtype.mojo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/src/builtin/dtype.mojo b/stdlib/src/builtin/dtype.mojo index 1391914b55..2c3545f70b 100644 --- a/stdlib/src/builtin/dtype.mojo +++ b/stdlib/src/builtin/dtype.mojo @@ -217,7 +217,7 @@ struct DType( Returns: The representation of the dtype. """ - return "DType." + str(self) + return String.write("DType.", self) @always_inline("nodebug") fn get_value(self) -> __mlir_type.`!kgen.dtype`: From 348b434ae4234856b41defb7ad75e5aaf03801c2 Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Thu, 7 Nov 2024 22:44:26 +0100 Subject: [PATCH 09/17] [stdlib] Simpler stat_result.__repr__() logic Signed-off-by: Manuel Saelices --- stdlib/src/os/fstat.mojo | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stdlib/src/os/fstat.mojo b/stdlib/src/os/fstat.mojo index cf5fa31181..ba298916d4 100644 --- a/stdlib/src/os/fstat.mojo +++ b/stdlib/src/os/fstat.mojo @@ -186,9 +186,7 @@ struct stat_result(Stringable, Writable): Returns: A string representation of stat_result. """ - var output = String() - self.write_to(output) - return output + return String.write(self) fn __repr__(self) -> String: """Constructs a representation of stat_result. From 97a7a961a3df07e2953bb27c7d91f7240e0aa20a Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Thu, 7 Nov 2024 22:47:46 +0100 Subject: [PATCH 10/17] [stdlib] Hopefully fix the test_stat() test in MacOS Signed-off-by: Manuel Saelices --- stdlib/test/pathlib/test_pathlib.mojo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/test/pathlib/test_pathlib.mojo b/stdlib/test/pathlib/test_pathlib.mojo index 4ab12d3242..3a77dbd6dd 100644 --- a/stdlib/test/pathlib/test_pathlib.mojo +++ b/stdlib/test/pathlib/test_pathlib.mojo @@ -152,7 +152,7 @@ def test_stat(): var path = Path(__source_location().file_name) var stat = path.stat() assert_true(stat.st_mode > 0) - assert_true(stat.st_size > 0) + assert_true(stat.st_size >= 0) assert_equal( str(stat), "os.stat_result(st_mode={}, st_ino={}, st_dev={}, st_nlink={}," From 40e27878d30496de7ff7d826a07cfe6fd5d0104c Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Thu, 7 Nov 2024 22:53:41 +0100 Subject: [PATCH 11/17] [stdlib] Simpler String.__repr__() logic Signed-off-by: Manuel Saelices --- magic.lock | 155 +++++++++++++++-------------- stdlib/src/collections/string.mojo | 4 +- 2 files changed, 79 insertions(+), 80 deletions(-) diff --git a/magic.lock b/magic.lock index 9bd07b0eb0..783a18d5b1 100644 --- a/magic.lock +++ b/magic.lock @@ -49,7 +49,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/email-validator-2.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/email_validator-2.2.0-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/fastapi-0.115.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fastapi-0.115.4-pyhff2d567_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fastapi-cli-0.0.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.16.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/frozenlist-1.5.0-py312h66e93f0_0.conda @@ -84,11 +84,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.1.0-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-25_linux64_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.11.0-hbbe4b11_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.10.1-hbbe4b11_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.3-h5888daf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.4-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-14.2.0-h77fa898_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.2.0-h69a702a_1.conda @@ -252,7 +252,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/email-validator-2.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/email_validator-2.2.0-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/fastapi-0.115.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fastapi-0.115.4-pyhff2d567_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fastapi-cli-0.0.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.16.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozenlist-1.5.0-py312hb2c0f52_0.conda @@ -288,11 +288,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlienc-1.1.0-h86ecc28_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.9.0-25_linuxaarch64_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcrc32c-1.1.2-h01db608_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.11.0-h3ec0cbf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.10.1-h3ec0cbf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libevent-2.1.12-h4ba1bb4_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.6.3-h5ad3122_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.6.4-h5ad3122_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.4.2-h3557bc0_5.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-14.2.0-he277a41_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-14.2.0-he9431aa_1.conda @@ -455,7 +455,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/email-validator-2.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/email_validator-2.2.0-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/fastapi-0.115.4-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/fastapi-0.115.4-pyhff2d567_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fastapi-cli-0.0.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.16.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/frozenlist-1.5.0-py312h0bf5046_0.conda @@ -489,12 +489,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.1.0-hd74edd7_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.9.0-25_osxarm64_openblas.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.11.0-he83c8a2_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.10.1-h13a7ad3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-19.1.3-ha82da77_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20191231-hc8eb9b7_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.3-hf9b8971_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.4-h286801f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-5.0.0-13_2_0_hd922786_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-13.2.0-hf226fd6_3.conda @@ -2268,27 +2268,28 @@ packages: - kind: conda name: fastapi version: 0.115.4 - build: pyhd8ed1ab_0 + build: pyhff2d567_1 + build_number: 1 subdir: noarch noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/fastapi-0.115.4-pyhd8ed1ab_0.conda - sha256: 69d319a58a7f929c047c0e6c1b845a3b384840ff95b1391516aa683f517f0929 - md5: 29841fbba8e0d4628ab513b92212def4 + url: https://conda.anaconda.org/conda-forge/noarch/fastapi-0.115.4-pyhff2d567_1.conda + sha256: a3c44aa26f49fa62bcb52b1c75136e41e2a0ca500e04a4f38fdfeb33bbd8a0f0 + md5: a5f092c747a80cf667c90d4a84372084 depends: - email_validator >=2.0.0 - fastapi-cli >=0.0.5 - httpx >=0.23.0 - jinja2 >=2.11.2 - pydantic >=1.7.4,!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0 - - python >=3.8 + - python >=3.9 - python-multipart >=0.0.7 - starlette >=0.40.0,<0.42.0 - typing_extensions >=4.8.0 - - uvicorn >=0.12.0 + - uvicorn-standard >=0.12.0 license: MIT license_family: MIT - size: 73156 - timestamp: 1730122842479 + size: 73441 + timestamp: 1730995430291 - kind: conda name: fastapi-cli version: 0.0.5 @@ -3584,65 +3585,65 @@ packages: timestamp: 1633683992603 - kind: conda name: libcurl - version: 8.11.0 - build: h3ec0cbf_0 - subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.11.0-h3ec0cbf_0.conda - sha256: 5abdd619874132899c9adf959c5ce06cb16c8b12caf91703baa6ea612f3d7e6b - md5: 124b069484210d870c2bf690c9f0666e + version: 8.10.1 + build: h13a7ad3_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.10.1-h13a7ad3_0.conda + sha256: 983a977c5627f975a930542c8aabb46089ec6ea72f28d9c4d3ee8eafaf2fc25a + md5: d84030d0863ffe7dea00b9a807fee961 depends: + - __osx >=11.0 - krb5 >=1.21.3,<1.22.0a0 - - libgcc >=13 - - libnghttp2 >=1.64.0,<2.0a0 + - libnghttp2 >=1.58.0,<2.0a0 - libssh2 >=1.11.0,<2.0a0 - libzlib >=1.3.1,<2.0a0 - openssl >=3.3.2,<4.0a0 - zstd >=1.5.6,<1.6.0a0 license: curl license_family: MIT - size: 440383 - timestamp: 1730894925285 + size: 379948 + timestamp: 1726660033582 - kind: conda name: libcurl - version: 8.11.0 - build: hbbe4b11_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.11.0-hbbe4b11_0.conda - sha256: ff59f5f33ad3cafc85ce64514e6d7e4bba9f229a6051dc26dffacb9680f1930e - md5: 610aa8fffc286c4d5784256fc6dd3bc6 + version: 8.10.1 + build: h3ec0cbf_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.10.1-h3ec0cbf_0.conda + sha256: 7c4983001c727f713b4448280ed4803d301087c184cd2819ba0b788ca62b73d1 + md5: f43539295c4e0cd15202d41bc72b8a26 depends: - - __glibc >=2.17,<3.0.a0 - krb5 >=1.21.3,<1.22.0a0 - libgcc >=13 - - libnghttp2 >=1.64.0,<2.0a0 + - libnghttp2 >=1.58.0,<2.0a0 - libssh2 >=1.11.0,<2.0a0 - libzlib >=1.3.1,<2.0a0 - openssl >=3.3.2,<4.0a0 - zstd >=1.5.6,<1.6.0a0 license: curl license_family: MIT - size: 421922 - timestamp: 1730894856634 + size: 439171 + timestamp: 1726659843118 - kind: conda name: libcurl - version: 8.11.0 - build: he83c8a2_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.11.0-he83c8a2_0.conda - sha256: d3c15bd0f1af42bf8304b81509bc9d1dac539b223be44c0acf522c155a865b9e - md5: b781cc008788d52982ee84c5ebb8996a + version: 8.10.1 + build: hbbe4b11_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.10.1-hbbe4b11_0.conda + sha256: 54e6114dfce566c3a22ad3b7b309657e3600cdb668398e95f1301360d5d52c99 + md5: 6e801c50a40301f6978c53976917b277 depends: - - __osx >=11.0 + - __glibc >=2.17,<3.0.a0 - krb5 >=1.21.3,<1.22.0a0 - - libnghttp2 >=1.64.0,<2.0a0 + - libgcc >=13 + - libnghttp2 >=1.58.0,<2.0a0 - libssh2 >=1.11.0,<2.0a0 - libzlib >=1.3.1,<2.0a0 - openssl >=3.3.2,<4.0a0 - zstd >=1.5.6,<1.6.0a0 license: curl license_family: MIT - size: 384193 - timestamp: 1730895277721 + size: 424900 + timestamp: 1726659794676 - kind: conda name: libcxx version: 19.1.3 @@ -3796,53 +3797,53 @@ packages: timestamp: 1685725977222 - kind: conda name: libexpat - version: 2.6.3 - build: h5888daf_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.3-h5888daf_0.conda - sha256: 4bb47bb2cd09898737a5211e2992d63c555d63715a07ba56eae0aff31fb89c22 - md5: 59f4c43bb1b5ef1c71946ff2cbf59524 + version: 2.6.4 + build: h286801f_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.4-h286801f_0.conda + sha256: e42ab5ace927ee7c84e3f0f7d813671e1cf3529f5f06ee5899606630498c2745 + md5: 38d2656dd914feb0cab8c629370768bf depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=13 + - __osx >=11.0 constrains: - - expat 2.6.3.* + - expat 2.6.4.* license: MIT license_family: MIT - size: 73616 - timestamp: 1725568742634 + size: 64693 + timestamp: 1730967175868 - kind: conda name: libexpat - version: 2.6.3 - build: h5ad3122_0 - subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.6.3-h5ad3122_0.conda - sha256: 02341c9c35128055fd404dfe675832b80f2bf9dbb99539457652c11c06e52757 - md5: 1d2b842bb76e268625e8ee8d0a9fe8c3 + version: 2.6.4 + build: h5888daf_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.4-h5888daf_0.conda + sha256: 56541b98447b58e52d824bd59d6382d609e11de1f8adf20b23143e353d2b8d26 + md5: db833e03127376d461e1e13e76f09b6c depends: + - __glibc >=2.17,<3.0.a0 - libgcc >=13 constrains: - - expat 2.6.3.* + - expat 2.6.4.* license: MIT license_family: MIT - size: 72342 - timestamp: 1725568840022 + size: 73304 + timestamp: 1730967041968 - kind: conda name: libexpat - version: 2.6.3 - build: hf9b8971_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.3-hf9b8971_0.conda - sha256: 5cbe5a199fba14ade55457a468ce663aac0b54832c39aa54470b3889b4c75c4a - md5: 5f22f07c2ab2dea8c66fe9585a062c96 + version: 2.6.4 + build: h5ad3122_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.6.4-h5ad3122_0.conda + sha256: f42e758009ba9db90d1fe7992bc3e60d0c52f71fb20923375d2c44ae69a5a2b3 + md5: f1b3fab36861b3ce945a13f0dfdfc688 depends: - - __osx >=11.0 + - libgcc >=13 constrains: - - expat 2.6.3.* + - expat 2.6.4.* license: MIT license_family: MIT - size: 63895 - timestamp: 1725568783033 + size: 72345 + timestamp: 1730967203789 - kind: conda name: libffi version: 3.4.2 diff --git a/stdlib/src/collections/string.mojo b/stdlib/src/collections/string.mojo index 5190c65842..c47329ffaa 100644 --- a/stdlib/src/collections/string.mojo +++ b/stdlib/src/collections/string.mojo @@ -1377,9 +1377,7 @@ struct String( Returns: A new representation of the string. """ - var output = String() - StringRepr(self).write_to(output) - return output + return String.write(StringRepr(self)) fn __fspath__(self) -> String: """Return the file system path representation (just the string itself). From 696339c632e4fe490b951d7e1553d8b5e243b8c0 Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Thu, 7 Nov 2024 22:55:11 +0100 Subject: [PATCH 12/17] [stdlib] Remove two failing checks in test_stat() which depends on the OS Signed-off-by: Manuel Saelices --- stdlib/test/pathlib/test_pathlib.mojo | 2 -- 1 file changed, 2 deletions(-) diff --git a/stdlib/test/pathlib/test_pathlib.mojo b/stdlib/test/pathlib/test_pathlib.mojo index 3a77dbd6dd..fc54c8f8d4 100644 --- a/stdlib/test/pathlib/test_pathlib.mojo +++ b/stdlib/test/pathlib/test_pathlib.mojo @@ -151,8 +151,6 @@ def test_home(): def test_stat(): var path = Path(__source_location().file_name) var stat = path.stat() - assert_true(stat.st_mode > 0) - assert_true(stat.st_size >= 0) assert_equal( str(stat), "os.stat_result(st_mode={}, st_ino={}, st_dev={}, st_nlink={}," From 3ab5ef09411b75bb7b69e8f2e7992dc12127d447 Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Tue, 12 Nov 2024 14:29:25 +0100 Subject: [PATCH 13/17] [stdlib] Adapt the code to s/unsafe_from_utf8_ptr/ptr refactoring Signed-off-by: Manuel Saelices --- stdlib/src/collections/string.mojo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/src/collections/string.mojo b/stdlib/src/collections/string.mojo index edcdd5a34b..599ad12bef 100644 --- a/stdlib/src/collections/string.mojo +++ b/stdlib/src/collections/string.mojo @@ -704,8 +704,8 @@ struct StringRepr(Writable): value: The string to represent. """ self._value = StringSlice[ImmutableAnyOrigin]( - unsafe_from_utf8_ptr=value.unsafe_ptr(), - len=len(value), + ptr=value.unsafe_ptr(), + length=len(value), ) fn write_to[W: Writer](self, inout writer: W): From 32a507ddfa4e140b3a5c88e0fce7d3d1701d36d8 Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Tue, 12 Nov 2024 14:32:35 +0100 Subject: [PATCH 14/17] [stdlib] Replace StringRepr to _StringRepr Signed-off-by: Manuel Saelices --- stdlib/src/collections/string.mojo | 4 ++-- stdlib/src/utils/stringref.mojo | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/src/collections/string.mojo b/stdlib/src/collections/string.mojo index 599ad12bef..11315f58d4 100644 --- a/stdlib/src/collections/string.mojo +++ b/stdlib/src/collections/string.mojo @@ -691,7 +691,7 @@ fn isprintable(c: UInt8) -> Bool: # ===----------------------------------------------------------------------=== # -struct StringRepr(Writable): +struct _StringRepr(Writable): """Represents a string representation of an String.""" var _value: StringSlice[ImmutableAnyOrigin] @@ -1382,7 +1382,7 @@ struct String( Returns: A new representation of the string. """ - return String.write(StringRepr(self)) + return String.write(_StringRepr(self)) fn __fspath__(self) -> String: """Return the file system path representation (just the string itself). diff --git a/stdlib/src/utils/stringref.mojo b/stdlib/src/utils/stringref.mojo index 6f644a063f..ddc9559ff1 100644 --- a/stdlib/src/utils/stringref.mojo +++ b/stdlib/src/utils/stringref.mojo @@ -15,7 +15,7 @@ from bit import count_trailing_zeros from builtin.dtype import _uint_type_of_width -from collections.string import _atol, _isspace, StringRepr +from collections.string import _atol, _isspace, _StringRepr from hashlib._hasher import _HashableWithHasher, _Hasher from memory import UnsafePointer, memcmp, pack_bits from memory.memory import _memcmp_impl_unconstrained @@ -408,7 +408,7 @@ struct StringRef( var to_str = str(self) output.write("StringRef(") - StringRepr(to_str).write_to(output) + _StringRepr(to_str).write_to(output) output.write(")") _ = to_str return output From 1ee14b11b70cb8bf197a9f6a5c06450fff392157 Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Tue, 12 Nov 2024 14:50:38 +0100 Subject: [PATCH 15/17] Fix typo in _StringRepr docstring Co-authored-by: Joe Loser Signed-off-by: Manuel Saelices --- stdlib/src/collections/string.mojo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/src/collections/string.mojo b/stdlib/src/collections/string.mojo index 11315f58d4..fcdd99f94f 100644 --- a/stdlib/src/collections/string.mojo +++ b/stdlib/src/collections/string.mojo @@ -692,7 +692,7 @@ fn isprintable(c: UInt8) -> Bool: struct _StringRepr(Writable): - """Represents a string representation of an String.""" + """Represents a string representation of a String.""" var _value: StringSlice[ImmutableAnyOrigin] """The string representation of the String.""" From cb66ec91854975df770a48206fa7688433ebaa2f Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Tue, 12 Nov 2024 16:26:34 +0100 Subject: [PATCH 16/17] [stdlib] Do not use _StringRepr for StringRef.__repr__() We will take advantage of a faster StringRef.__repr__() when https://github.com/modularml/mojo/pull/3686 was merged Signed-off-by: Manuel Saelices --- stdlib/src/utils/stringref.mojo | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/stdlib/src/utils/stringref.mojo b/stdlib/src/utils/stringref.mojo index ddc9559ff1..0d1ede078e 100644 --- a/stdlib/src/utils/stringref.mojo +++ b/stdlib/src/utils/stringref.mojo @@ -15,7 +15,7 @@ from bit import count_trailing_zeros from builtin.dtype import _uint_type_of_width -from collections.string import _atol, _isspace, _StringRepr +from collections.string import _atol, _isspace from hashlib._hasher import _HashableWithHasher, _Hasher from memory import UnsafePointer, memcmp, pack_bits from memory.memory import _memcmp_impl_unconstrained @@ -404,14 +404,7 @@ struct StringRef( Returns: The String representation of the StringRef. """ - var output = String() - var to_str = str(self) - - output.write("StringRef(") - _StringRepr(to_str).write_to(output) - output.write(")") - _ = to_str - return output + return String.write("StringRef(", repr(str(self)), ")") @no_inline fn write_to[W: Writer](self, inout writer: W): From 958106b0828bf84af3beefae4cfc19ef1f9edf12 Mon Sep 17 00:00:00 2001 From: Manuel Saelices Date: Tue, 12 Nov 2024 16:30:58 +0100 Subject: [PATCH 17/17] [stdlib] Revert the StringRepr logic as there is a much better approach waiting for being merged here: https://github.com/modularml/mojo/pull/3686 Signed-off-by: Manuel Saelices --- stdlib/src/collections/string.mojo | 86 ++++++++++-------------------- 1 file changed, 28 insertions(+), 58 deletions(-) diff --git a/stdlib/src/collections/string.mojo b/stdlib/src/collections/string.mojo index fcdd99f94f..917b56e99b 100644 --- a/stdlib/src/collections/string.mojo +++ b/stdlib/src/collections/string.mojo @@ -686,63 +686,6 @@ fn isprintable(c: UInt8) -> Bool: return ord_space <= int(c) <= ord_tilde -# ===----------------------------------------------------------------------=== # -# String Representation -# ===----------------------------------------------------------------------=== # - - -struct _StringRepr(Writable): - """Represents a string representation of a String.""" - - var _value: StringSlice[ImmutableAnyOrigin] - """The string representation of the String.""" - - fn __init__(inout self, value: String): - """Constructs a string representation of the string. - - Args: - value: The string to represent. - """ - self._value = StringSlice[ImmutableAnyOrigin]( - ptr=value.unsafe_ptr(), - length=len(value), - ) - - fn write_to[W: Writer](self, inout writer: W): - """Writes the string representation to the provided writer. - - Parameters: - W: The type of the writer. - - Args: - writer: The writer to write the string representation to. - """ - var quote = "'" - if len(self._value) > 0 and self._value[0] == "'": - quote = '"' - writer.write(quote) - for s in self._value: - if s == "\\": - writer.write(r"\\") - elif s == "\t": - writer.write(r"\t") - elif s == "\n": - writer.write(r"\n") - elif s == "\r": - writer.write(r"\r") - else: - var codepoint = ord(s) - if isprintable(codepoint): - writer.write(s) - elif codepoint < 0x10: - writer.write(hex(codepoint, prefix=r"\x0")) - elif codepoint < 0x20 or codepoint == 0x7F: - writer.write(hex(codepoint, prefix=r"\x")) - else: # multi-byte character - writer.write(s) - writer.write(quote) - - # ===----------------------------------------------------------------------=== # # String # ===----------------------------------------------------------------------=== # @@ -1382,7 +1325,34 @@ struct String( Returns: A new representation of the string. """ - return String.write(_StringRepr(self)) + var result = String() + var use_dquote = False + for s in self: + use_dquote = use_dquote or (s == "'") + + if s == "\\": + result += r"\\" + elif s == "\t": + result += r"\t" + elif s == "\n": + result += r"\n" + elif s == "\r": + result += r"\r" + else: + var codepoint = ord(s) + if isprintable(codepoint): + result += s + elif codepoint < 0x10: + result += hex(codepoint, prefix=r"\x0") + elif codepoint < 0x20 or codepoint == 0x7F: + result += hex(codepoint, prefix=r"\x") + else: # multi-byte character + result += s + + if use_dquote: + return '"' + result + '"' + else: + return "'" + result + "'" fn __fspath__(self) -> String: """Return the file system path representation (just the string itself).