Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import: command not found #6

Closed
DutchPete opened this issue Sep 2, 2020 · 39 comments
Closed

Import: command not found #6

DutchPete opened this issue Sep 2, 2020 · 39 comments
Labels
bug Something isn't working

Comments

@DutchPete
Copy link

Here is what I tried via the terminal; please advise:

Peters-MacBook-Air:~ peter$ defaults write net.ankiweb.dtop NSAppSleepDisabled -bool true
Peters-MacBook-Air:~ peter$ defaults write net.ichi2.anki NSAppSleepDisabled -bool true
Peters-MacBook-Air:~ peter$ defaults write org.qt-project.Qt.QtWebEngineCore NSAppSleepDisabled -bool true
Peters-MacBook-Air:~ peter$ /Volumes/NO\ NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 1: Sc: command not foundds to Anki from Obsidian.
: command not foundripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 2: 
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 3: import: command not found
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 4: import: command not found
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 5: import: command not found
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 6: import: command not found
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 7: import: command not found
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 8: import: command not found
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 9: import: command not found
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 10: import: command not found
: command not foundripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 11: 
: command not foundripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 12: 
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 13: syntax error near unexpected token `('
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 13: `'ef write_safe(filename, contents):
Peters-MacBook-Air:~ peter$ cd /Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/
-bash: cd: /Volumes/NO: No such file or directory
Peters-MacBook-Air:~ peter$ cd /Volumes/NO\ NAME/Scripts/Obsidian_to_Anki-master/
Peters-MacBook-Air:Obsidian_to_Anki-master peter$ ./obsidian_to_anki.py
: command not foundpy: line 1: Script for adding cards to Anki from Obsidian.
: command not foundpy: line 2: 
./obsidian_to_anki.py: line 3: import: command not found
./obsidian_to_anki.py: line 4: import: command not found
./obsidian_to_anki.py: line 5: import: command not found
./obsidian_to_anki.py: line 6: import: command not found
./obsidian_to_anki.py: line 7: import: command not found
./obsidian_to_anki.py: line 8: import: command not found
./obsidian_to_anki.py: line 9: import: command not found
./obsidian_to_anki.py: line 10: import: command not found
: command not foundpy: line 11: 
: command not foundpy: line 12: 
./obsidian_to_anki.py: line 13: syntax error near unexpected token `('
'/obsidian_to_anki.py: line 13: `def write_safe(filename, contents):
@Pseudonium
Copy link
Collaborator

Hmm, it's giving a syntax error. What does the .py file look like in an editor?

Also, which release did you download?

@DutchPete
Copy link
Author

I downloaded the release 10 mins. ago.

Not sure what you mean by "What does the .py file look like in an editor?"

@Pseudonium
Copy link
Collaborator

Pseudonium commented Sep 2, 2020

As in, open it in a text editor. The equivalent of Notepad. Could you copy/paste what it looks like in the editor?

Also, did you download it directly from the repository, or from the releases tab?

@DutchPete
Copy link
Author

I downloaded the zip file from here.
Editor output:

"""Script for adding cards to Anki from Obsidian."""

import re
import json
import urllib.request
import configparser
import os
import argparse
import collections
import webbrowser


def write_safe(filename, contents):
    """
    Write contents to filename while keeping a backup.

    If write fails, a backup 'filename.bak' will still exist.
    """
    with open(filename + ".tmp", "w") as temp:
        temp.write(contents)
    os.rename(filename, filename + ".bak")
    os.rename(filename + ".tmp", filename)
    success = False
    with open(filename) as f:
        if f.read() == contents:
            success = True
    if success:
        os.remove(filename + ".bak")


def string_insert(string, position_inserts):
    """
    Insert strings in position_inserts into string, at indices.

    position_inserts will look like:
    [(0, "hi"), (3, "hello"), (5, "beep")]
    """
    offset = 0
    for position, insert_str in position_inserts:
        string = "".join(
            [
                string[:position + offset],
                insert_str,
                string[position + offset:]
            ]
        )
        offset += len(insert_str)
    return string


class AnkiConnect:
    """Namespace for AnkiConnect functions."""

    def request(action, **params):
        """Format action and parameters into Ankiconnect style."""
        return {'action': action, 'params': params, 'version': 6}

    def invoke(action, **params):
        """Do the action with the specified parameters."""
        requestJson = json.dumps(
            AnkiConnect.request(action, **params)
        ).encode('utf-8')
        response = json.load(urllib.request.urlopen(
            urllib.request.Request('http://localhost:8765', requestJson)))
        if len(response) != 2:
            raise Exception('response has an unexpected number of fields')
        if 'error' not in response:
            raise Exception('response is missing required error field')
        if 'result' not in response:
            raise Exception('response is missing required result field')
        if response['error'] is not None:
            raise Exception(response['error'])
        return response['result']


class FormatConverter:
    """Converting Obsidian formatting to Anki formatting."""

    INLINE_MATH_REGEXP = re.compile(r"(?<!\$)\$(?=[\S])(?=[^$])[\s\S]*?\S\$")
    DISPLAY_MATH_REGEXP = re.compile(r"\$\$[\s\S]*?\$\$")

    ANKI_INLINE_START = r"\("
    ANKI_INLINE_END = r"\)"

    ANKI_DISPLAY_START = r"\["
    ANKI_DISPLAY_END = r"\]"

    def inline_anki_repl(matchobject):
        """Get replacement string for Obsidian-formatted inline math."""
        found_string = matchobject.group(0)
        # Strip Obsidian formatting by removing first and last characters
        found_string = found_string[1:-1]
        # Add Anki formatting
        result = FormatConverter.ANKI_INLINE_START + found_string
        result += FormatConverter.ANKI_INLINE_END
        return result

    def display_anki_repl(matchobject):
        """Get replacement string for Obsidian-formatted display math."""
        found_string = matchobject.group(0)
        # Strip Obsidian formatting by removing first two and last two chars
        found_string = found_string[2:-2]
        # Add Anki formatting
        result = FormatConverter.ANKI_DISPLAY_START + found_string
        result += FormatConverter.ANKI_DISPLAY_END
        return result

    def obsidian_to_anki_math(note_text):
        """Convert Obsidian-formatted math to Anki-formatted math."""
        return FormatConverter.INLINE_MATH_REGEXP.sub(
            FormatConverter.inline_anki_repl,
            FormatConverter.DISPLAY_MATH_REGEXP.sub(
                FormatConverter.display_anki_repl, note_text
            )
        )

    def format(note_text):
        """Apply all format conversions to note_text."""
        note_text = FormatConverter.obsidian_to_anki_math(note_text)
        return note_text


class Note:
    """Manages parsing notes into a dictionary formatted for AnkiConnect.

    Input must be the note text.
    Does NOT deal with finding the note in the file.
    """

    TARGET_DECK = "Default"
    ID_PREFIX = "ID: "
    TAG_PREFIX = "Tags: "
    TAG_SEP = " "
    Note_and_id = collections.namedtuple('Note_and_id', ['note', 'id'])

    def __init__(self, note_text):
        """Set up useful variables."""
        self.text = FormatConverter.format(note_text)
        self.lines = self.text.splitlines()
        self.note_type = Note.note_subs[self.lines[0]]
        self.subs = Note.field_subs[self.note_type]
        self.current_field_num = 0
        self.field_names = list(self.subs)
        if self.lines[-1].startswith(Note.ID_PREFIX):
            self.identifier = int(self.lines.pop()[len(Note.ID_PREFIX):])
            # The above removes the identifier line, for convenience of parsing
        else:
            self.identifier = None
        if self.lines[-1].startswith(Note.TAG_PREFIX):
            self.tags = self.lines.pop()[len(Note.TAG_PREFIX):].split(
                Note.TAG_SEP
            )
        else:
            self.tags = None

    @property
    def NOTE_DICT_TEMPLATE(self):
        """Template for making notes."""
        return {
            "deckName": Note.TARGET_DECK,
            "modelName": "",
            "fields": dict(),
            "options": {
                "allowDuplicate": False,
                "duplicateScope": "deck"
            },
            "tags": ["Obsidian_to_Anki"],
            # ^So that you can see what was added automatically.
            "audio": list()
        }

    @property
    def current_field(self):
        """Get the field to add text to."""
        return self.field_names[self.current_field_num]

    @property
    def current_sub(self):
        """Get the prefix substitution of the current field."""
        return self.subs[self.current_field]

    @property
    def next_field(self):
        """Attempt to get the next field to add text to."""
        try:
            return self.field_names[self.current_field_num + 1]
        except IndexError:
            return ""

    @property
    def next_sub(self):
        """Attempt to get the substitution of the next field."""
        try:
            return self.subs[self.next_field]
        except KeyError:
            return ""

    @property
    def fields(self):
        """Get the fields of the note into a dictionary."""
        fields = dict.fromkeys(self.field_names, "")
        for line in self.lines[1:]:
            if self.next_sub and line.startswith(self.next_sub):
                self.current_field_num += 1
                line = line[len(self.current_sub):]
            fields[self.current_field] += line + " "
        return {key: value.rstrip() for key, value in fields.items()}

    def parse(self):
        """Get a properly formatted dictionary of the note."""
        template = self.NOTE_DICT_TEMPLATE.copy()
        template["modelName"] = self.note_type
        template["fields"] = self.fields
        if self.tags:
            template["tags"] = template["tags"] + self.tags
        return Note.Note_and_id(note=template, id=self.identifier)


class Config:
    """Deals with saving and loading the configuration file."""

    CONFIG_PATH = os.path.dirname(__file__) + "/obsidian_to_anki_config.ini"

    def update_config():
        """Update config with new notes."""
        print("Updating configuration file...")
        config = configparser.ConfigParser()
        config.optionxform = str
        if os.path.exists(Config.CONFIG_PATH):
            print("Config file exists, reading...")
            config.read(Config.CONFIG_PATH)
        note_types = AnkiConnect.invoke("modelNames")
        fields_request = [
            AnkiConnect.request(
                "modelFieldNames", modelName=note
            )
            for note in note_types
        ]
        subs = {
            note: {
                field: field + ": "
                for field in fields["result"]
            }
            for note, fields in zip(
                note_types,
                AnkiConnect.invoke(
                    "multi", actions=fields_request
                )
            )
        }
        for note, note_field_subs in subs.items():
            if note not in config:
                config[note] = dict()
            for field, sub in note_field_subs.items():
                config[note].setdefault(field, sub)
                # This means that, if there's already a substitution present,
                # the 'default' substitution of field + ": " isn't added.
        if "Note Substitutions" not in config:
            config["Note Substitutions"] = dict()
        for note in note_types:
            config["Note Substitutions"].setdefault(note, note)
            # Similar to above - if there's already a substitution present,
            # it isn't overwritten
        with open(Config.CONFIG_PATH, "w") as configfile:
            config.write(configfile)
        print("Configuration file updated!")

    def load_config():
        """Load from an existing config file (assuming it exists)."""
        print("Loading configuration file...")
        config = configparser.ConfigParser()
        config.optionxform = str  # Allows for case sensitivity
        config.read(Config.CONFIG_PATH)
        note_subs = config["Note Substitutions"]
        Note.note_subs = {v: k for k, v in note_subs.items()}
        Note.field_subs = {
            note: dict(config[note]) for note in config
            if note != "Note Substitutions" and note != "DEFAULT"
        }
        print("Loaded successfully!")


class App:
    """Master class that manages the application."""

    # Useful REGEXPs
    NOTE_REGEXP = re.compile(r"(?<=START\n)[\s\S]*?(?=END\n?)")
    DECK_REGEXP = re.compile(r"(?<=TARGET DECK\n)[\s\S]*?(?=\n)")

    def __init__(self):
        """Execute the main functionality of the script."""
        self.setup_parser()
        args = self.parser.parse_args()
        if args.update:
            Config.update_config()
        Config.load_config()
        if args.config:
            webbrowser.open(Config.CONFIG_PATH)
            return
        if args.filename:
            self.filename = args.filename
            print("Reading file", args.filename, "into memory...")
            with open(args.filename) as f:
                self.file = f.read()
            self.target_deck = App.DECK_REGEXP.search(self.file).group(0)
            if self.target_deck is not None:
                Note.TARGET_DECK = self.target_deck
            print("Identified target deck as", Note.TARGET_DECK)
            self.scan_file()
            self.add_notes()
            self.write_ids()
            self.update_fields()
            self.get_info()
            self.get_cards()
            self.move_cards()
            self.get_tags()
            self.clear_tags()
            self.add_tags()

    def setup_parser(self):
        """Set up the argument parser."""
        self.parser = argparse.ArgumentParser(
            description="Add cards to Anki from an Obsidian markdown file."
        )
        self.parser.add_argument(
            "-f",
            type=str,
            help="The file you want to add flashcards from.",
            dest="filename"
        )
        self.parser.add_argument(
            "-c", "--config",
            action="store_true",
            dest="config",
            help="""
                Opens up config file for editing.
            """
        )
        self.parser.add_argument(
            "-u", "--update",
            action="store_true",
            dest="update",
            help="""
                Whether you want to update the config file
                using new notes from Anki.
                Note that this does NOT open the config file for editing,
                use -c for that.
            """,
        )

    def scan_file(self):
        """Sort notes from file into adding vs editing."""
        print("Scanning file for notes...")
        self.notes_to_add = list()
        self.id_indexes = list()
        self.notes_to_edit = list()
        for note_match in App.NOTE_REGEXP.finditer(self.file):
            note, position = note_match.group(0), note_match.end()
            parsed = Note(note).parse()
            if parsed.id is None:
                self.notes_to_add.append(parsed.note)
                self.id_indexes.append(position)
            else:
                self.notes_to_edit.append(parsed)

    @staticmethod
    def id_to_str(id):
        """Get the string repr of id."""
        return "ID: " + str(id) + "\n"

    def add_notes(self):
        """Add notes to Anki."""
        print("Adding notes into Anki...")
        self.identifiers = map(
            App.id_to_str, AnkiConnect.invoke(
                "addNotes",
                notes=self.notes_to_add
            )
        )

    def write_ids(self):
        """Write the identifiers to the file."""
        print("Writing new note IDs to file...")
        self.file = string_insert(
            self.file, zip(
                self.id_indexes, self.identifiers
            )
        )
        write_safe(self.filename, self.file)

    def update_fields(self):
        """Update the fields of current notes."""
        print("Updating fields of existing notes...")
        AnkiConnect.invoke(
            "multi",
            actions=[
                AnkiConnect.request(
                    "updateNoteFields", note={
                        "id": parsed.id,
                        "fields": parsed.note["fields"],
                        "audio": parsed.note["audio"]
                    }
                )
                for parsed in self.notes_to_edit
            ]
        )

    def get_info(self):
        """Get info on all notes to be edited."""
        print("Getting info on notes to be edited...")
        self.info = AnkiConnect.invoke(
            "notesInfo",
            notes=[
                parsed.id for parsed in self.notes_to_edit
            ]
        )

    def get_cards(self):
        """Get the card IDs for all notes that need to be edited."""
        print("Getting card IDs")
        self.cards = list()
        for info in self.info:
            self.cards += info["cards"]

    def move_cards(self):
        """Move all cards to target deck."""
        print("Moving cards to target deck...")
        AnkiConnect.invoke(
            "changeDeck",
            cards=self.cards,
            deck=self.target_deck
        )

    def get_tags(self):
        """Get a set of currently used tags for notes to be edited."""
        self.tags = set()
        for info in self.info:
            self.tags.update(info["tags"])

    def clear_tags(self):
        """Remove all currently used tags from notes to be edited."""
        print("Replacing tags...")
        AnkiConnect.invoke(
            "removeTags",
            notes=[parsed.id for parsed in self.notes_to_edit],
            tags=" ".join(self.tags)
        )

    def add_tags(self):
        """Add user-set tags for notes to be edited."""
        AnkiConnect.invoke(
            "multi",
            actions=[
                AnkiConnect.request(
                    "addTags",
                    notes=[parsed.id],
                    tags=" ".join(parsed.note["tags"])
                )
                for parsed in self.notes_to_edit
                if parsed.note["tags"]
            ]
        )


if __name__ == "__main__":
    if not os.path.exists(Config.CONFIG_PATH):
        Config.update_config()
    App()

@Pseudonium
Copy link
Collaborator

Hmm, I copy-pasted your output into a python file and ran it, and it worked.

What version of python do you have installed?

@DutchPete
Copy link
Author

2.7.16

@DutchPete
Copy link
Author

I am a bit confused by Python because I did upgrade to 3 and yesterday it showed that as the version, today it does not. This is not the 1st time Python does that.

@Pseudonium
Copy link
Collaborator

Ah, that must be the problem. I wrote the script for python3 (specifically 3.8).

I'll add that to the documentation, for future reference.

I'm guessing it would be too much hassle to install python 3.8?

@DutchPete
Copy link
Author

Look at this output from my terminal and note Python:

Peters-MacBook-Air:Obsidian_to_Anki-master peter$ brew list
cask-repair	gdbm		icu4c		python@3.8	xz
coreutils	gnu-sed		node		readline
dart		hr		openssl@1.1	sass
espanso		hub		pandoc		sqlite

@Pseudonium
Copy link
Collaborator

Hmm, this is techincally outside the functionality of the script, but I'll see if I can help.

From this link - try running python --version

@DutchPete
Copy link
Author

Peters-MacBook-Air:Obsidian_to_Anki-master peter$ python3 --version
Python 3.8.3
Peters-MacBook-Air:Obsidian_to_Anki-master peter$ python --version
Python 2.7.16

@Pseudonium
Copy link
Collaborator

So according to that website, that means 2.7.16 is your default version, even though 3.8.3 is installed.

You might want to take a look at this stackoverflow question

@DutchPete
Copy link
Author

Thanks for that link. I had found another page, where someone suggested making a symlink, which I did. And indeed, the correct Python version is shown. Then I ran the initial script, but no joy. Here is all the output:

Last login: Wed Sep  2 13:08:52 on ttys000
Peters-MacBook-Air:~ peter$ ln -s -f /usr/local/bin/python3.8 /usr/local/bin/python
Peters-MacBook-Air:~ peter$ python --version
Python 3.8.3
Peters-MacBook-Air:~ peter$ /Volumes/NO\ NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 1: Sc: command not foundds to Anki from Obsidian.
: command not foundripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 2: 
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 3: import: command not found
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 4: import: command not found
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 5: import: command not found
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 6: import: command not found
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 7: import: command not found
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 8: import: command not found
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 9: import: command not found
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 10: import: command not found
: command not foundripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 11: 
: command not foundripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 12: 
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 13: syntax error near unexpected token `('
/Volumes/NO NAME/Scripts/Obsidian_to_Anki-master/obsidian_to_anki.py: line 13: `'ef write_safe(filename, contents):

@Pseudonium
Copy link
Collaborator

Hmm, it’s still showing the syntax error.

Try running python3 obsidian_to_anki.py

@DutchPete
Copy link
Author

Getting there, though not quite yet:

Peters-MacBook-Air:~ peter$ cd /Volumes/NO\ NAME/Scripts/Obsidian_to_Anki-master/
Peters-MacBook-Air:Obsidian_to_Anki-master peter$ python3 obsidian_to_anki.py
Updating configuration file...
Traceback (most recent call last):
  File "obsidian_to_anki.py", line 467, in <module>
    Config.update_config()
  File "obsidian_to_anki.py", line 264, in update_config
    with open(Config.CONFIG_PATH, "w") as configfile:
PermissionError: [Errno 13] Permission denied: '/obsidian_to_anki_config.ini'

@Pseudonium
Copy link
Collaborator

Yes, progress!

You should check the ‘Permissions’ section in README.md. It lists what the script needs to be able to do on an OS level.

@DutchPete
Copy link
Author

DutchPete commented Sep 2, 2020

The Permissions section does not say which file needs to be given permission.
I want to do chmod +x <filename>, but for which file? obsidian_to_anki_config.ini does not exist yet.

@Pseudonium
Copy link
Collaborator

Just the script I think. The config file is just a text file.

@DutchPete
Copy link
Author

No joy:

Peters-MacBook-Air:Obsidian_to_Anki-master peter$ chmod +x obsidian_to_anki.py
Peters-MacBook-Air:Obsidian_to_Anki-master peter$ python3 obsidian_to_anki.py
Updating configuration file...
Traceback (most recent call last):
  File "obsidian_to_anki.py", line 467, in <module>
    Config.update_config()
  File "obsidian_to_anki.py", line 264, in update_config
    with open(Config.CONFIG_PATH, "w") as configfile:
PermissionError: [Errno 13] Permission denied: '/obsidian_to_anki_config.ini'

@Pseudonium
Copy link
Collaborator

The chmod+x only makes it executable I think. It’ll need permission to read and write in order to work properly.

@DutchPete
Copy link
Author

The info box about the file says it has read and write permission.

@Pseudonium
Copy link
Collaborator

Hmm, I’m not really sure what else it could be, since the error is that the script cannot make a new file for writing.

Is it in a special folder that has restrictions on creating files?

@DutchPete
Copy link
Author

No, not a special folder.

I think I'll wait for the appearance of the API and someone (you?) to write a plug-in. That'll be much easier.

@Pseudonium
Copy link
Collaborator

Ok. If you want to do one last check, see if you can write a simple python script in that folder which creates and writes to a file. If you can, that’ll confirm the problem is with my script. If you get a similar error, it’s probably something on your end.

@DutchPete
Copy link
Author

I am not familiar with writing python scripts. And in any case, I do believe it'll be easier to use a plug-in.
I appreciate your patience and help you have given me, many thanks for that.

@Pseudonium
Copy link
Collaborator

Pseudonium commented Sep 2, 2020

If you want a script that should work, I’ll give an example (though of course you can just wait for the plugin)

with open("test.txt", "w") as f:
    f.write("Hello world!")

@DutchPete
Copy link
Author

So, the script you wrote I can save as e.g. test.py?
Then place it in the Obsidian_to_Anki-master folder,
Then run it as python3 test.py
Is that right?

@Pseudonium
Copy link
Collaborator

Yep, just tested it and it works. Should just be able to copy-paste it in.

@DutchPete
Copy link
Author

Yes, that works. It created a test.txt file with Hello world in it.

@DutchPete
Copy link
Author

I have to step away from my desk, back in a couple of hours.

@Pseudonium
Copy link
Collaborator

Ah, I think I finally figured out the problem.

Config.CONFIG_PATH is the variable that stores the path to the config file (so that the script can be run from anywhere while still accessing its config file).

However, the way I created the path was taking the path for the script, getting the directory, and concatenating "/obsidian_to_anki_config.ini".
The "/" probably messes things up on non-Windows file systems.

I've changed the way Config.CONFIG_PATH is generated so that it should work (v0.3.1). If you don't mind, once you're back at your desk, could you check if it works on your system?

@DutchPete
Copy link
Author

I just download the zip package again but there's no mention of v0.3.1, so where can I get it from?

@Pseudonium
Copy link
Collaborator

Ah sorry - you’ll want v0.3.2 or v0.4 now (v0.4 also requires python-markdown, check README)

@DutchPete
Copy link
Author

Sorry, I must be dumb, but Read.me is the same as before. Where can I get 0.4 from?
What is python-markdown?

@Pseudonium
Copy link
Collaborator

While you were away, I released v0.4. It’s called ‘Markdown formatting and Embedded Images Update’. This link should work.

v0.4 introduces a new dependency, python-markdown. The current README.md should be updated - check Setup step 6.

@DutchPete
Copy link
Author

I downloaded the .py file from the linked-to page.
Pip is not a command macOS knows.

@Pseudonium
Copy link
Collaborator

Hmm, pip should be installed with python. See if you can get pip to work if you have it, or install it if you don’t.

@DutchPete
Copy link
Author

Success, I believe:

Peters-MacBook-Air:Obsidian_to_Anki-master peter$ python3 obsidian_to_anki.py
Updating configuration file...
Configuration file updated!
Loading configuration file...
Loaded successfully!

@Pseudonium
Copy link
Collaborator

Great! I’ll close this issue now - if you have any further problems, please open a new issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants