# Migrating to 3.0

If you have a working program using NXT-Python 2, you will have to make changes to port it to NXT-Python 3.

## Porting to Python 3

First of all you need to port your code to Python 3, there is an guide in Python documentation. You do not need to worry about keeping the code compatible with Python 2 as it is no longer supported.

There is also an automatic script to ease the porting, called 2to3.

One major change in Python is the distinction between text string (`str`) and binary string (`bytes`). This means that you need to make sure to use the right one when passing arguments to NXT-Python functions.

## Porting to NXT-Python 3

Next step is to adapt the code for NXT-Python.

### Major Changes

The `nxt.locator.find_one_brick()` function has been removed and replaced with the simpler `nxt.locator.find()` function. Actually, the whole `nxt.locator` has been replaced.

Many debug arguments have been removed, now NXT-Python uses the `logging` module to log messages. If you want to enable debug messages, use this code before calling any NXT-Python function:

    import logging
    logging.basicConfig(level=logging.DEBUG)

The `nxt` and `nxt.sensor` modules no longer exports name from sub-modules. In general, NXT-Python now avoids to have two names for the same object.

Output port constants are replaced by enumerations, using the `enum` module:

NXT-Python 2 | NXT-Python 3
--- | ---
`PORT_A` | `Port.A`
`PORT_B` | `Port.B`
`PORT_C` | `Port.C`
`MODE_IDLE` | `Mode.IDLE`
`MODE_MOTOR_ON` | `Mode.ON`
`MODE_BRAKE` | `Mode.BRAKE`
`MODE_REGULATED` | `Mode.REGULATED`
`REGULATION_IDLE` | `RegulationMode.IDLE`
`REGULATION_MOTOR_SPEED` | `RegulationMode.SPEED`
`REGULATION_MOTOR_SYNC` | `RegulationMode.SYNC`
`RUN_STATE_IDLE` | `RunState.IDLE`
`RUN_STATE_RAMP_UP` | `RunState.RAMP_UP`
`RUN_STATE_RUNNING` | `RunState.RUNNING`
`RUN_STATE_RAMP_DOWN` | `RunState.RAMP_DOWN`

You can now create `nxt.motor.Motor` objects using `nxt.brick.Brick.get_motor()`, however direct creation still works.

Input port constants are replaced by enumerations, using the `enum` module. The `nxt.sensor.common` module has been removed, its content is directly available in `nxt.sensor`:

NXT-Python 2 | NXT-Python 3
--- | ---
`PORT_1` | `Port.S1`
`PORT_2` | `Port.S2`
`PORT_3` | `Port.S3`
`PORT_4` | `Port.S4`
`Type.NO_SENSOR` | `Type.NO_SENSOR`
`Type.SWITCH` | `Type.SWITCH`
`Type.TEMPERATURE` | `Type.TEMPERATURE`
`Type.REFLECTION` | `Type.REFLECTION`
`Type.ANGLE` | `Type.ANGLE`
`Type.LIGHT_ACTIVE` | `Type.LIGHT_ACTIVE`
`Type.LIGHT_INACTIVE` | `Type.LIGHT_INACTIVE`
`Type.SOUND_DB` | `Type.SOUND_DB`
`Type.SOUND_DBA` | `Type.SOUND_DBA`
`Type.CUSTOM` | `Type.CUSTOM`
`Type.LOW_SPEED` | `Type.LOW_SPEED`
`Type.LOW_SPEED_9V` | `Type.LOW_SPEED_9V`
`Type.HIGH_SPEED` | `Type.HIGH_SPEED`
`Type.COLORFULL` | `Type.COLOR_FULL`
`Type.COLORRED` | `Type.COLOR_RED`
`Type.COLORGREEN` | `Type.COLOR_GREEN`
`Type.COLORBLUE` | `Type.COLOR_BLUE`
`Type.COLORNONE` | `Type.COLOR_NONE`
`Type.COLOREXIT` | `Type.COLOR_EXIT`
`Mode.RAW` | `Mode.RAW`
`Mode.BOOLEAN` | `Mode.BOOL`
`Mode.TRANSITION_CNT` | `Mode.EDGE`
`Mode.PERIOD_COUNTER` | `Mode.PULSE`
`Mode.PCT_FULL_SCALE` | `Mode.PERCENT`
`Mode.CELSIUS` | `Mode.CELSIUS`
`Mode.FAHRENHEIT` | `Mode.FAHRENHEIT`
`Mode.ANGLE_STEPS` | `Mode.ROTATION`
`Mode.MASK` | Removed
`Mode.MASK_SLOPE` | Removed

You can now create `sensor` objects using `nxt.brick.Brick.get_sensor()`, however direct creation still works. For digital sensors with identification information, this can automatically detect the sensor type as with previous version. The new cls argument allows creating a sensor object using another class.

### Text String or Binary String

The NXT brick only understands ASCII, so this is the default encoding used in NXT-Python.

From `nxt.brick.Brick`:

- `get_device_info()` now returns a `str` for the brick name.

- `file_write()`, `write_io_map()` and `message_write()` now take `bytes` instead of a `str`.

- `file_read()`, `read_io_map()` and `poll_command()` no longer return the read size, but the returned `bytes` object is cut to the right size.

- `get_current_program_name()` returns a `str`.

- `file_delete()` is fixed and returns a `str`.

- `find_files()` and `find_modules()` use `str` for file and module names.

### File Access

File reading and writing are now implemented using classes implementing `io.RawIOBase`. When using `open_file()`, depending of the parameters, the raw file-like object is returned directly, or wrapped in a `io.BufferedIOBase` or `io.TextIOBase` object.

Default access mode is now text with ASCII encoding, you need to ask explicitly for binary if needed.

This means that file access should be similar to regular Python file access.

### Renamed

From `nxt.brick.Brick`:

- `delete()` has been renamed to `file_delete()`.

- Many low level file and module access methods now have a `file_` or `module_` prefix. They are however not supposed to be used directly.

From `nxt.error`:

- `DirProtError` and `SysProtError` have been renamed to `DirectProtocolError` and `SystemProtocolError`.

- `FileNotFound` has been renamed to `FileNotFoundError`.

- `ModuleNotFound` has been renamed to `ModuleNotFoundError`.

- New `EmptyMailboxError` and `NoActiveProgramError` have been added as subclasses of `DirectProtocolError`.

Sensors:

- `nxt.sensor.generic.Color20` has been renamed to `nxt.sensor.generic.Color`.

### Removed

Some attributes are now private (prefixed with `_`).

Support for the lightblue module has been removed. It has been integrated into PyBluez.

From `nxt.brick`:

- `Brick.open_read_linear()` has been removed, it has never been accessible from outside the NXT brick.

- `File`, `FileReader` and `FileWriter` have been removed, use `Brick.open_file()`.

- `FileFinder` has been removed, use `Brick.find_files()`.

- `ModuleFinder` has been removed, use `Brick.find_modules()`.

- `Brick.mc` has been removed, make an instance using:

      mc = nxt.motcont.MotCont(the_brick)

From other modules:

- `nxt.motcont.MotCont.move_to()` has been removed as it is not part of MotorControl interface and its role was not clear.

- `nxt.motcont.MotorConError` has been removed and replaced with `nxt.error.ProtocolError`.

- `nxt.telegram.InvalidReplyError` and `nxt.telegram.InvalidOpcodeError` have been removed and replaced with `nxt.error.ProtocolError`.

Module `nxt.utils` has been removed, use `argparse`.

### Other Changes

From `nxt.brick.Brick`:

- `get_device_info()` returns a tuple for the Bluetooth signal strength values instead of a single 32 bit value.

- `find_files()` and `find_modules()` return an empty iterator instead of raising an exception when no file or module is found.

- `close()` now closes the connection to the NXT brick. Also `Brick` now implements the context manager interface so that it can be used with the `with` syntax.

- `boot()` now takes a argument to avoid accidental firmware erasure.

Other:

- `nxt.motcont.MotCont` methods accept tuple as argument to control several ports.

- Scripts command line interface has changed.