<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>emre şahin's digital garden 🍃 - debugging</title>
    <link>https://emresahin.net/tags/debugging/</link>
    <description>Posts in the debugging tag</description>
    <language>en</language>
    <managingEditor>contact@emresahin.net (Emre Şahin)</managingEditor>
    <lastBuildDate>Tue, 29 Sep 2026 14:57:43 +0000</lastBuildDate>
    <atom:link href="https://emresahin.net/tags/debugging/rss.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>devlog 2</title>
      <published>2024-05-26T17:29:09+00:00</published>
      <updated>2024-05-26T17:29:09+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Sun, 26 May 2024 17:29:09 +0000</pubDate>
      <link>https://emresahin.net/devlog-2/</link>
      <guid isPermaLink="true">https://emresahin.net/devlog-2/</guid>
      <description>We were debugging Python bindings for Xvc. xvc.file.track enters an infinite loop when given a non-existent path. To make debugging easier, we can add file deletions in the ./start-readme script to the notebook itself. Instead, I’ll run my watcher run-after-commit.sh to ensure that the files are ...</description>
      <category>devlog</category>
      <category>xvc</category>
      <category>xvc</category>
      <category>jupyter</category>
      <category>xvc-config</category>
      <category>xvc-file</category>
      <category>repr</category>
      <category>python-bindings</category>
      <category>debugging</category>
      <content:encoded><![CDATA[<p>We were debugging Python bindings for Xvc. <code>xvc.file.track</code> enters an infinite
loop when given a non-existent path.</p>
<p>To make debugging easier, we can add file deletions in the <code>./start-readme</code> script
to the notebook itself.</p>
<p>Instead, I’ll run my watcher <code>run-after-commit.sh</code> to ensure that the files
are deleted after commits.</p>
<p>That may also work; you can use both as well.</p>
<p>I noticed cli-opts pass <code>--no-system-config</code> etc. by default. Let’s deal with
this first.</p>
<p>I fixed that.</p>
<p>I’m testing whether we are in the directory that we should be in with
<code>xvc.root("--absolute")</code>, but it looks like it’s not possible to pass a string
argument to the command.</p>
<p>Let me take a look at this.</p>
<p>It looks like there have been some changes in optional parameter handling in PyO3.
You may need to deal with keyword arguments with decorators.</p>
<p>Now, let’s try <code>xvc.file().track()</code> once more with <code>dir-0001/</code>.</p>
<p>It seems to be working now. With an existing directory, it doesn’t show an
error.</p>
<p>What does <code>xvc.file().list()</code> show?</p>
<p>It shows a single string with <code>\n</code> in it. It looks like we need to handle this in
the output thread.</p>
<p>I added a <code>replace("\\n", "\n")</code> to <code>output_str</code> at the end, but it didn’t make a
difference. I tested in the notebook with <code>list_result.split("\n")</code>, and these
<code>\n</code> characters are indeed CRLF. So Jupyter shows CRLF in strings with <code>\n</code>, and
this is not something we should try to fix, I think.</p>
<p>You can search how to show <code>\n</code> characters in a Jupyter notebook with CRLF.</p>
<p>The output string should be fed into <code>repr</code>, as in:</p>
<pre><code class="language-python"># Define a string with CRLF characters
text_crlf = "Hello\r\nWorld\r\nThis is a test string."

# Use repr to show the \r\n characters explicitly
print(repr(text_crlf))
</code></pre>
<p>I tested this, and GPT misleads. <code>repr</code> is when you <em>want</em> to show <code>\n</code>, not
vice versa. When I <code>print(list_result)</code>, it prints the results properly.</p>
<p>It looks like we don’t need to make this a priority now. We can tell the user in the
notebook that the commands are intentionally returning strings, and they can
process or print them however they want.</p>]]></content:encoded>
    </item>
    <item>
      <title>Devlog 1: XVC Root and Python Bindings Debugging</title>
      <published>2024-05-24T10:12:50+00:00</published>
      <updated>2024-05-24T10:12:50+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Fri, 24 May 2024 10:12:50 +0000</pubDate>
      <link>https://emresahin.net/devlog-1/</link>
      <guid isPermaLink="true">https://emresahin.net/devlog-1/</guid>
      <description>I should have a dispatch method that receives an XvcRootOpt and runs a command with it. The dispatcher can also update the XvcRoot from None to Some(XvcRoot) in some cases, so it should receive a mutable XvcRootOpt or return one after receiving ownership. The issue with having a mutable element i...</description>
      <category>Devlog</category>
      <category>XVC</category>
      <category>xvc</category>
      <category>debugging</category>
      <category>shell</category>
      <category>jupyter-lab</category>
      <category>rust</category>
      <category>python-bindings</category>
      <content:encoded><![CDATA[<p>I should have a dispatch method that receives an <code>XvcRootOpt</code> and runs a command
with it. The dispatcher can also update the <code>XvcRoot</code> from <code>None</code> to <code>Some(XvcRoot)</code>
in some cases, so it should receive a mutable <code>XvcRootOpt</code> or return one after
receiving ownership.</p>
<p>The issue with having a mutable element is that we need to update <code>XvcRoot</code> from
<code>Arc&lt;XvcRootInner&gt;</code> to <code>Arc&lt;RwLock&lt;XvcRootInner&gt;&gt;</code>, which will cause almost all
machinery around <code>XvcRoot</code> to require locking the object first. This is too
large a refactoring.</p>
<p>However, I can write an <code>xvc_root!</code> macro to replace <code>xvc_root.read()</code> or
whatever is required to minimize the code changes. <code>XvcRoot</code> can also be a wrapper
object, but that’s too much fuss, and the responsibility may be misplaced.</p>
<p>Let’s update the type and let the dispatcher update <code>XvcRootInner</code> only
when necessary. Let’s see what will require updating.</p>
<hr>
<p>We have a bug in the Python bindings where <code>xvc.file.track()</code> enters an infinite loop.</p>
<p>There can be multiple reasons, but are you sure that the <code>xvc</code> CLI works with the
same command?</p>
<p>Let’s start testing by creating another notebook server.</p>
<p>The notebook creates an Xvc repo successfully and returns the root with
<code>xvc.root()</code>, but <code>xvc.file().track("test-data/dir-0001/")</code> never finishes.</p>
<p>It’s likely that this is caused by something in the background threads.</p>
<p>The CLI command completes successfully, but we may be passing the command
incorrectly. Let’s try <code>dir-0001</code> only.</p>
<p>Even if an incorrect path is provided, it shouldn’t enter an infinite loop.</p>
<p>When I provide the correct path, <code>dir-0001</code>, it returns. There may be something going on with finding the root of the Xvc repo.</p>
<p>It returns, but it’s also giving an error that it cannot find a repository. I should take a closer look.</p>
<p>The <code>Xvc</code> struct wasn’t implementing <code>Debug</code>, so I added it.</p>
<p>Let’s add it to others, <code>XvcFile</code>, etc.</p>
<p>Added it. Recompiling to get more info when we run <code>track</code> with an incorrect path.</p>
<p>You can also make it run after a commit to avoid starting a new server if one is already running.</p>
<p>Added conditionals, and now it runs the server if none is running in the background.</p>
<pre><code class="language-zsh">PORT=7979
if [[ ! -s "$(ps ax | rg -v ps | rg jupyter-lab | rg $PORT)" ]] ; then
  jupyter lab --port=$PORT --notebook-dir=Readme/ &amp;
  open http://localhost:${PORT}/lab/workspaces/auto-H/tree/Readme.ipynb
fi
</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Xvc Devlog 221030</title>
      <published>2022-10-31T08:57:00+00:00</published>
      <updated>2022-10-31T08:57:00+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Mon, 31 Oct 2022 08:57:00 +0000</pubDate>
      <link>https://emresahin.net/xvc-devlog-221030/</link>
      <guid isPermaLink="true">https://emresahin.net/xvc-devlog-221030/</guid>
      <description>🐇 We’ll start by checking the repository today. What are the most important issues? 🐢 I’ve merged PR#66 . Let’s list the outstanding issues now. 65 OPEN Add Mermaid Support to Netlify Installation 64 OPEN Fix `xvc-storage` compilation warnings bug 54 OPEN Fix all references to `xvc data` in the d...</description>
      <category>devlog</category>
      <category>Software Development</category>
      <category>github actions</category>
      <category>arc42</category>
      <category>debugging</category>
      <category>xvc storage</category>
      <category>tests</category>
      <category>s3cmd</category>
      <content:encoded><![CDATA[<p>🐇 We’ll start by checking <a href="https://github.com/iesahin/xvc">the repository</a> today. What are the most important issues?</p>
<p>🐢 I’ve merged <a href="https://github.com/iesahin/xvc/pull/66">PR#66</a>. Let’s list the outstanding issues now.</p>
<pre><code>65	OPEN	Add Mermaid Support to Netlify Installation
64	OPEN	Fix `xvc-storage` compilation warnings	bug
54	OPEN	Fix all references to `xvc data` in the documentation
51	OPEN	Add a benchmark script to compare Xvc with other tools
50	OPEN	Consider changing `xvc file push` to `xvc file send` and `xvc file pull` to `xvc file retrieve`
49	OPEN	Add `--generic-command` as a dependency type to `xvc pipeline dependency`
48	OPEN	Write rsync example for `xvc storage generic`	documentation
47	OPEN	Write rclone example for `xvc storage generic`	documentation
46	OPEN	Allow to skip init in remotes with `--skip-init` option
45	OPEN	Update `VStore::to_store` to use some internal mechanism to avoid `XvcStore::insert`
43	OPEN	Update to `clap 4.0`
42	OPEN	Clean up xvc crate dependencies
36	OPEN	Add version to released file binaries
33	OPEN	Update `arch/remotes.md` for new naming	documentation
32	OPEN	Remove arc42 sections from the documentation	documentation
29	OPEN	Add documentation for `xvc storage new gcs`	documentation
28	OPEN	`xvc storage new yandex`	enhancement
24	OPEN	Create a logo for Xvc	documentation
23	OPEN	Add a Github action to upload new versions to crates.io	automation
20	OPEN	ref: Add rsync example for `xvc storage new generic`
18	OPEN	Add a new workflow for remote tests	automation
12	OPEN	Create a website for Xvc
5	OPEN	Add storage tests to Github Actions	automation
4	OPEN	fix clippy warnings	bug
1	OPEN	`xvc storage new` for all S3 compatible cloud services supported by `rust-s3`
</code></pre>
<p>🐇 As far as I know, you removed the arc42 stubs from the docs yesterday. You can close issue #32.</p>
<p>🐢 I closed it via <code>gh issue close</code>.</p>
<p>🐇 You should add a comment to that.</p>
<p>🐢 Added the comment.</p>
<hr>
<p>🐇 It’s October 30th. Looking at the logs, you’ve <a href="https://github.com/iesahin/xvc/issues?q=is%3Aissue+is%3Aclosed">closed some more issues since we last talked.</a></p>
<p>🐢 I’ve been productive over the last few days. Now, let’s take a look at the <a href="https://github.com/iesahin/xvc/issues?q=is%3Aopen+is%3Aissue">open</a> issues.</p>
<p>🐇 I think you have a more pressing problem. <a href="https://github.com/iesahin/xvc/actions/runs/3352401264">Your tests</a> are failing. You need to fix them first before moving to another task.</p>
<p>🐢 Created a new <a href="https://github.com/iesahin/xvc/issues/81">issue</a>. The logs say:</p>
<pre><code>81Z error: 7 targets failed:
2022-10-29T18:18:36.8969467Z ##[error]    `-p xvc-workflow-tests --test test_storage_new_digital_ocean`
2022-10-29T18:18:36.8970697Z     `-p xvc-workflow-tests --test test_storage_new_gcp`
2022-10-29T18:18:36.8971279Z     `-p xvc-workflow-tests --test test_storage_new_generic_rsync`
2022-10-29T18:18:36.8971840Z     `-p xvc-workflow-tests --test test_storage_new_minio`
2022-10-29T18:18:36.8972387Z     `-p xvc-workflow-tests --test test_storage_new_r2`
2022-10-29T18:18:36.8973035Z     `-p xvc-workflow-tests --test test_storage_new_s3`
2022-10-29T18:18:36.8973577Z     `-p xvc-workflow-tests --test test_storage_new_wasabi`
2022-10-29T18:18:36.9368079Z ##[error]The process '/home/runner/.cargo/bin/cargo' failed with exit code 101
</code></pre>
<p>🐇 Looking at the logs, you should clean up those older branches.</p>
<p>🐢 Let’s do it now.</p>
<hr>
<p>🐢 Done. I’ve deleted all branches except <code>main</code>.</p>
<p>🐇 Good. I think the best way is to delete them as soon as you merge them.</p>
<p>🐢 I’ve activated that setting. These were older branches.</p>
<p>🐇 Cool. Now, will you be checking the failing tests?</p>
<p>🐢 I think remote tests should never run if there are other errors. We can run coverage and remote tests as a second step after the first succeed.</p>
<p>🐇 That seems like a neat idea. You want to split the current job into two: one for compiling and testing the non-remote parts, and the second for coverage and storage tests. It won’t waste CI minutes that way?</p>
<p>🐢 On second thought, I think at the moment, that’s not a pressing issue. We should start fixing these tests at once. We can split them later.</p>
<p>🐇 Ok. It looks from the logs like secrets are not being made available to your jobs.</p>
<pre><code>2022-10-29T18:18:17.5039311Z test test_storage_new_digital_ocean ... FAILED
2022-10-29T18:18:17.5039550Z
2022-10-29T18:18:17.5039652Z failures:
2022-10-29T18:18:17.5039784Z
2022-10-29T18:18:17.5040197Z ---- test_storage_new_digital_ocean stdout ----
2022-10-29T18:18:17.5040558Z Error: VarError { source: NotPresent }
2022-10-29T18:18:17.5040758Z
2022-10-29T18:18:17.5040765Z
</code></pre>
<p>🐢 I added them now. Let’s wait until the job ends to get a new set of logs.</p>
<p>🐇 You can write some documentation in the meantime.</p>
<p>🐢 I think <a href="https://github.com/iesahin/xvc/issues/82">#82</a> is a good candidate for this. There must not be too many missing docs in the ECS crate.</p>
<p>🐇 It was about <code>walker</code> and you fixed the <code>ecs</code>. You’re the most absentminded developer here, I believe.</p>
<p>🐢 Ooops, you’re right. I’ll add them together in a <a href="https://github.com/iesahin/xvc/pull/93">single PR.</a></p>
<p>🐇 In the meantime, the storage testing job has ended with 🔴.</p>
<p>🐢 Checking the raw logs. It looks like we didn’t update the tests to match the current options:</p>
<pre><code>2022-10-30T14:45:50.1058348Z error: Found argument '--storage-prefix' which wasn't expected, or isn't valid in this context
2022-10-30T14:45:50.1059809Z ##[error]Found argument '--storage-prefix' which wasn't expected, or isn't valid in this context
2022-10-30T14:45:50.1061740Z 	If you tried to supply `--storage-prefix` as a value rather than a flag, use `-- --storage-prefix`
2022-10-30T14:45:50.1063220Z
2022-10-30T14:45:50.1063394Z USAGE:
2022-10-30T14:45:50.1064302Z     xvc storage new digital-ocean --name &lt;NAME&gt; --bucket-name &lt;BUCKET_NAME&gt; --region &lt;REGION&gt;
</code></pre>
<p>🐇 Is it <code>--storage-prefix</code> or <code>--remote-prefix</code>? Which one is clearer?</p>
<p>🐢 I think updating the tests to conform to the current options is better for now. We can update the options later if desired.</p>
<p>🐇 Another failure is <code>rg</code>. You assume it exists on the testing system.</p>
<p>🐢 <code>ripgrep</code> is available in Ubuntu 20.04, so we can just update the initial package list.</p>
<p>🐇 The same <code>--storage-prefix</code> failure appears in the <code>minio</code> tests.</p>
<p>🐢 Ok. Fixing it.</p>
<p>🐇 S3 tests want to run the <code>new-s3</code> subcommand. I think we now see why we need these tests in the first place.</p>
<p>🐢 Yeah. Fixing the prefix option, too.</p>
<p>🐇 <code>s3cmd</code> is also required. You should add it, too.</p>
<p>🐢 Ok. I think we’ve added all missing dependencies. I’ll have to convert the <code>mc</code> tests for Minio to use <code>s3cmd</code>.</p>
<p>🐇 Then we can try again. Now, we can get back to documentation.</p>
<p>🐢 Added some more documentation to PR#93. I think it’s better to return to the storage test errors now.</p>
<p>🐇 It looks like you have missing DigitalOcean credentials.</p>
<p>🐢 Let’s take a look.</p>
<hr>
<p>🐢 I’ve updated the tests to use a config file instead of command-line arguments that would be visible in the logs.</p>
<p>🐇 Good practice. You also need to remove previous logs.</p>
<p>🐢 Maybe there is an option for that.</p>
<p>🐇 It looks like there isn’t. There are masking options; when we add them to secrets, they are masked. But you shouldn’t use them in calls anyway.</p>]]></content:encoded>
    </item>
    <item>
      <title>Rust `ends_with` and `strip_prefix` behavior differences in `Path` and `str`</title>
      <published>2022-07-06T16:03:51+00:00</published>
      <updated>2022-07-06T16:03:51+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Wed, 06 Jul 2022 16:03:51 +0000</pubDate>
      <link>https://emresahin.net/Rust--ends_with--and--strip_prefix--behavior-differences-in--Path--and--str-/</link>
      <guid isPermaLink="true">https://emresahin.net/Rust--ends_with--and--strip_prefix--behavior-differences-in--Path--and--str-/</guid>
      <description>While writing an ignore library, I encountered subtle bugs caused by Rust’s Path behavior. ends_with in Path is different from ends_with in str : If you try to check whether a Path is a directory by its final character, you’ll find that path.ends_with("/") returns false . Path::strip_prefix also ...</description>
      <category>development</category>
      <category>rust</category>
      <category>programming</category>
      <category>rust</category>
      <category>Path</category>
      <category>str</category>
      <category>std</category>
      <category>debugging</category>
      <content:encoded><![CDATA[<p>While writing an ignore library, I encountered subtle bugs caused by Rust’s <code>Path</code> behavior.</p>
<ul>
<li>
<p><strong><code>ends_with</code> in <code>Path</code> is different from <code>ends_with</code> in <code>str</code></strong>:
If you try to check whether a <code>Path</code> is a directory by its final character, you’ll find that <code>path.ends_with("/")</code> returns <code>false</code>.</p>
</li>
<li>
<p><strong><code>Path::strip_prefix</code> also consumes the final slash</strong>:
If you have a directory marker at the end, such as <code>/Users/emre/mydir/</code>, and pass it to <code>strip_prefix("/Users/emre")</code>, you’ll get <code>mydir</code> instead of <code>mydir/</code>.</p>
</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Query Logging in Databases when using Parameters</title>
      <published>2018-11-06T19:41:10+00:00</published>
      <updated>2018-11-06T19:41:10+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Tue, 06 Nov 2018 19:41:10 +0000</pubDate>
      <link>https://emresahin.net/query-logging-in-python-sqlite-14359-20562/</link>
      <guid isPermaLink="true">https://emresahin.net/query-logging-in-python-sqlite-14359-20562/</guid>
      <description>We avoid constructing database queries using string formatting to prevent security issues. SQL injection attacks stem from a lack of proper escaping and building queries directly from untrusted input strings. Instead, we use parameter passing to the database engine. For example: SELECT * FROM peo...</description>
      <category>Databases</category>
      <category>Python</category>
      <category>sqlite</category>
      <category>query-logging</category>
      <category>debugging</category>
      <category>sql-injection</category>
      <category>security</category>
      <content:encoded><![CDATA[<p>We avoid constructing database queries using string formatting to prevent security issues. SQL injection attacks stem from a lack of proper escaping and building queries directly from untrusted input strings.</p>
<p>Instead, we use parameter passing to the database engine. For example:</p>
<pre><code class="language-sql">SELECT * FROM people WHERE name = ?
</code></pre>
<p>We send this query and the parameters separately to the database. Most modern database systems support this approach.</p>
<p>In SQLite 3 with Python, we use it like this:</p>
<pre><code class="language-python">query = "SELECT * FROM people WHERE name = ?"
params = (name,)
db_result = cursor.execute(query, params)
</code></pre>
<p>However, when debugging, we may need to see the actual queries sent to the database—for instance, when data types are important or when we suspect a column is receiving a string instead of an integer.</p>
<p>In these cases, rather than manually reconstructing the query, we can use the <code>set_trace_callback</code> feature available in Python 3.3 and later:</p>
<pre><code class="language-python">connection.set_trace_callback(print)
</code></pre>
<p>The argument can be any function (such as <code>print</code> or a logger function) or <code>None</code> to disable tracing. This makes it easy to integrate with Python’s standard <code>logging</code> module.</p>]]></content:encoded>
    </item>
  </channel>
</rss>
